C++ 在具有通用引用参数的函数模板中使用类模板
根据msvc、gcc和clang的说法,以下代码是非法的:C++ 在具有通用引用参数的函数模板中使用类模板,c++,templates,c++11,gcc,C++,Templates,C++11,Gcc,根据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); } 但是我看不到函数模板f在哪里引用了int 有人能解释一下我们在这里看到的编译器错误吗?当用左值int调用f时,T将被推断为in
template <typename T>
void f(T&& e) {
std::vector<T> v;
// do something with v and e ...
}
int main() {
int i;
f(i);
}
但是我看不到函数模板f
在哪里引用了int
有人能解释一下我们在这里看到的编译器错误吗?当用左值
int
调用f
时,T
将被推断为int&
,因此v
将是std::vector
。这是无效的
解决此问题的一种方法是在使用之前从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 ...
}
模板
无效f(T&e){
使用value\u type=typename std::remove\u reference::type;
//对C++14使用value\u type=std::remove\u reference
std::向量v;
//用v和e做点什么。。。
}
但是,如果希望函数尽可能通用,则应使用
std::decay
而不是std::remove\u reference
。这将允许f
使用cv限定的类型、数组和函数。Scott Meyers在本文中解释
如果初始化通用引用的表达式是左值,则
通用引用变为左值引用
如果表达式
初始化通用引用是一个右值,即通用引用
引用变为右值引用
在您的例子中,
i
是一个左值,因此T
被推断为int&
注意,转发引用现在是首选术语。虽然标记了c++11
,但可能也建议删除引用\u T
,以防万一?这使它成为一个很好的一行。@YamMarcovic谢谢,我在中添加了这一点,尽管我更愿意在两行而不是一行中添加。读者注意:我想强调的是,由于f是一个函数模板,所以根据答案引用的规则,当f被实例化为左值时,即使std::vector中的T也变成了T。之前,我的理解是std::vector中的T不能与.@Angle.Bracket中的T不同,基于这个评论,您似乎仍然没有清楚的理解;在template
中,它表示有一个名为T
的模板参数。std::vector
中的T
就是同一个参数T
不会变成T&
。相反,在您的示例中,T
是类型int&
<代码>向量变为向量
,因为T
被推导为int&
(从编译器错误消息中可以看到)。您可以通过尝试f(i),在不调用类型推断的情况下再现该行为代码>vs.f(i)代码>。这肯定需要衰减
,而不是删除参考
(带或不带删除cv
)。
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 ...
}