c++

模板实参推断

Posted by ysd on August 13, 2016

类型转换

  • 编译器通常不对实参进行类型转换,而是生成新的模板实例
  • 将实参传递给带模板类型的函数形参时,能够自动应用的类型转换:
    1. 顶层const被忽略
    2. 可以将非const对象的引用或指针传递给const的引用或指针形参
    3. 如果函数参数不是引用,则可将数组或函数转成指针
  • 注意:
    1. 算数转换/子类向父类转换/用户自定义都不能应用与函数模板
    2. 数组大小不同是不同类型,此时如果形参是T,则被转化为指针,数组大小不赶紧要; 如果形参是引用,如T&,数组不会转成指针,数组的大小也是数组类型的一部分

引用折叠

  • 当一个函数参数是一个右值引用,可以传递一个右值
template <typename T> void f3(T&&);
f3(42); // T是int
  • 此时传递一个左值也是可以的(虽然通常不能将右值引用绑定到左值上), 当调用f3(i)时(i是一个左值),编译器推断T为int&
  • T被推断为int&好像f3的参数是一个int&的右值引用(通常直接不能定义引用的引用), 如果我们间接创建引用的引用,这些引用形成了 折叠
    1. T& &, T& &&, T&& &会折叠成T&
    2. T&& &&会折叠成T&&
  • 上面两个规则使得我们可以传递任意类型的实参给T&&类型的函数形参(传递左值将会化为左值引用)

std::move

template <typename T>
// 使用typename表示后面的东西是个类型
typename remove_reference<T>::type&& move(T&& t) {
    // remove_reference::type脱去引用,返回类型本身
    // static_cast可以显示的将左值转换为右值引用
    return static_cast<typename remove_reference<T>::type&&>(t);
}
  • 通过引用折叠,T&&可以和任何类型的实参匹配,可以传递左值,也可以传递右值
  • move调用告诉编译器:我们有一个左值,但希望像一个右值一样处理他。 可以销毁移后源对象,也可赋予新值,但不能使用它