如您所知,_Remove_reference 的存在是为了将 T& 转换为 T 或将 T&& 转换为 T。
我怀着一种玩乐的心情写了下面的代码,它根本没有像我预期的那样工作,但不知道为什么。
template<class _Ty>
struct _Remove_reference
{ // remove reference
typedef _Ty _Type;
static void func(){ cout << "1" << endl; }
};
// template<class _Ty>
// struct _Remove_reference<_Ty&>
// { // remove reference
// typedef _Ty _Type;
// static void func(){ cout << "2" << endl; }
// };
//
// template<class _Ty>
// struct _Remove_reference<_Ty&&>
// { // remove rvalue reference
// typedef _Ty _Type;
// static void func(){ cout << "3" << endl; }
// };
template<class _Ty> inline
typename _Remove_reference<_Ty>::_Type&&
move(_Ty&& _Arg)
{ // forward _Arg as movable
typename _Remove_reference<_Ty>::func();
return ((typename _Remove_reference<_Ty>::_Type&&)_Arg);
}
int main(){
int a1= 3;
int&& a2 = move(a1); // can't convert the a1 to int&&
return 0;
}
我想这都是关于引用折叠规则和模板参数推导,但我很困惑。必须打破我对此的好奇心才能睡个好觉。
提前致谢。
最佳答案
给定
template<class _Ty> inline
typename _Remove_reference<_Ty>::_Type&&
move(_Ty&& _Arg)
当你执行 move(a1)
时,_Ty
被推断为 int&
。由于引用折叠规则,_Ty&&
仍将是 int&
,因此您需要先删除引用以获取 int
,然后才能将其设为右值引用。
这是模板参数推导规则的一个特例。如果你有一个函数参数是 T&&
其中 T
是一个模板参数,那么如果你传递一个左值(即命名对象或左值引用)给函数然后T
推导为 X&
,其中 X
是左值对象的类型。如果您将右值(临时或右值引用)传递给函数,则 T
将被推导为 X
。
例如move(a1)
推导出 _Ty
为 int&
,而 move(42)
推导出 _Ty
为 int
。
顺便说一句:我猜你从编译器的标准库中获取了这段代码 --- 用前导下划线和大写字母修饰的名称 _Like _This 是为编译器和标准库实现保留的。
关于c++ - 为什么 std::move() 没有 _Remove_reference 就不能工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8307238/