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 &&
:
- 如果
T
是 U
那么你会得到 U &&
.
- 如果
T
是 U &
那么你会得到 U & &&
,它会折叠成 U &
。
- 如果
T
是 U &&
那么你会得到 U && &&
,它会折叠成 U &&
。
std::remove_reference
将 "remove" 来自某个类型的左值引用或右值引用,导致 T &
和 T &&
变为 T
.
因此,如果您的 T
是 U &
,则 return 类型不同:
- 您的第一个示例 returns
U & &&
实际上是 U &
-- 完全不是我们想要的 std::move()
到 return!
- 你的第二个例子returns
U &&
.
正确:
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 &&
:
- 如果
T
是U
那么你会得到U &&
. - 如果
T
是U &
那么你会得到U & &&
,它会折叠成U &
。 - 如果
T
是U &&
那么你会得到U && &&
,它会折叠成U &&
。
std::remove_reference
将 "remove" 来自某个类型的左值引用或右值引用,导致 T &
和 T &&
变为 T
.
因此,如果您的 T
是 U &
,则 return 类型不同:
- 您的第一个示例 returns
U & &&
实际上是U &
-- 完全不是我们想要的std::move()
到 return! - 你的第二个例子returns
U &&
.