c++中模板的实例化

instantiation of templates in c++

正确:

template<typename T>
typename remove_reference<T>::type&& move(T&&d){
  return static_cast<typename remove_reference<T>::type&&>(d);
}

错误:

template<typename T>
T&& move(T&&d){
  return static_cast<typename remove_reference<T>::type&&>(d);
}

我不明白这些模板函数的实例化方式有何不同。这两个函数的 return 类型有何不同?

你需要考虑当你用不同的类型调用第二个版本时会发生什么,引用折叠将导致以下结果:

int a{};
move(a); // return type deduced as int& &&, i.e. int&
move(1); // return type deduced as int&& &&, i.e. int&&

第一个版本将始终生成右值引用类型,这正是您想要的 move

这是 reference collapsing rules of C++11 的结果。

当你的类型为 T &&:

  • 如果 TU 那么你会得到 U &&.
  • 如果 TU & 那么你会得到 U & &&,它会折叠成 U &
  • 如果 TU && 那么你会得到 U && &&,它会折叠成 U &&

std::remove_reference 将 "remove" 来自某个类型的左值引用或右值引用,导致 T &T && 变为 T.

因此,如果您的 TU &,则 return 类型不同:

  • 您的第一个示例 returns U & && 实际上是 U & -- 完全不是我们想要的 std::move() 到 return!
  • 你的第二个例子returns U &&.