Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在具有通用引用参数的函数模板中使用类模板_C++_Templates_C++11_Gcc - Fatal编程技术网

C++ 在具有通用引用参数的函数模板中使用类模板

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

根据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
将被推断为
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 ...
}