根据msvc,gcc和clang,以下代码是非法的:
template <typename T>
void f(T&& e) {
std::vector<T> v;
// do something with v and e ...
}
int main() {
int i;
f(i);
}
msvc产生
xmemory0(591):错误C2528:&#39;指针&#39;:指向引用的指针是 非法
gcc和clang给出类似的声音错误消息。请注意,不使用通用引用参数e
。编译器显然无法实例化向量v
,抱怨它与int
的引用一起使用:
注意:请参阅类模板实例化的引用 正在编译
'std::vector<T,std::allocator<_Ty>>'
与[ T=int &, _Ty=int & ]
但我无法通过引用f
来查看函数模板int
的实例化。
有人可以解释我们在这里看到的编译器错误吗?
答案 0 :(得分:18)
使用左值f
调用int
时,T
将推断为int&
,因此v
将为std::vector<int&>
。这是无效的。
解决此问题的一种方法是在使用前删除T
中的引用:
template <typename T>
void f(T&& e) {
using value_type = typename std::remove_reference<T>::type;
//using value_type = std::remove_reference_t<T>; for C++14
std::vector<value_type> v;
// do something with v and e ...
}
但是,如果您希望该功能尽可能通用,则应使用std::decay
代替std::remove_reference
。这将允许f
使用cv限定类型,数组和函数。
答案 1 :(得分:7)
Scott Meyers在此article中解释。
如果初始化通用引用的表达式是左值,则 通用引用成为左值引用。
如果表达 初始化通用引用是一个rvalue,通用 引用成为右值引用。
在您的情况下,i
是左值,因此T
推断为int&
。