在之前的 文章 中,谈到了对于 std::bind 的一些 VC++ 上的实现细节,作为之前的延续,也顺便调查了一下常用的 std::forward 的实现机制.

std::forward 是在模板编程中常用的一个函数,主要用于将当前函数的参数原封不动地传入内部的函数(完美转发),就像 std::bind
实现中的那样:

std::forward 的定义则是这样的

在实际使用中因为上面的定义,就需要显式指定模板参数,于是下面的代码尝试利用模板推导,来免去指定模板参数的麻烦.

上面的forward会根据参数的类型,来获取Ty,进行一系列模板操作.虽然实际上forward并应该不限定输入的参数必须是左值(也就是说代码写错了),不过通过以下的测试,发现了一些有趣的东西.

可以发现,无论输入的是左值,还是右值,推导出的类型都是int,并不是期望的int&,或int&&,自然 std::enable_if 会永远匹配失败.
也就是说,实际上推导的规则使得 myForward 永远无法得到想要的结果.

让我们重新参考一下 C++文档 中对于模板参数推导的描述,可以整理出以下规则:

    1. std::initializer_list<T>(初始化列表,比如你用大括号来初始化 std::vector<T> 之类的) 进行参数推导时,会对大括号中每个单独的值进行推导(移除修饰符之类的),当每个值的推导结果都相同时,视为匹配成功,如下所示:

      *注:C++17后还可以推导出大括号里有几个值,好厉害好厉害….x
    2. 对于 可变参数列表 的情况,则会对里面每个参数单独进行推导,最终的结果合并在一起就是可变参数列表的结果(参考 std::forward 的定义)
    3. 模板参数可以从 函数,函数指针(成员函数也可以哦) 的参数列表中的类型 进行类型推导,推导过程会对那个函数的所有重载进行检查,当有且仅有一个推导成功的重载时,推导成功,如下所示:

      *注:进一步说,对于函数还可以推导出成员函数所属类的哦:
    4. 对于单个参数的推导,则会按照以下的规则进行推导

从上面的规则中可以发现,上面 myForward,是无法推导出想要的结果的.(不过换成_Ty&& Arg后似乎可以用了…之后再测试下具体效果有没有区别….~)

*注:在 模板推导的文档 中,也详细说明了所有可以推导场合的列表,可以去看以下
*注2:封面依然是f7(eiki)的画(曾经做过手机封面~~(喜欢w