类模板与函数模板中的右值引用 [英] rvalue reference in class template vs function template

查看:62
本文介绍了类模板与函数模板中的右值引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

#include <iostream>

template <typename T>
class test
{
public:
    test(T&& t)
    {
    }
};

template <typename T>
void succeed(T&& t)
{
}

int main()
{
    int i = 1;
    test<int> t(i);    // failed to compile
    succeed(i);        // OK
    return 0;
}

来自GCC 5.2的错误:main.cpp:在函数'int main()'中:main.cpp:20:18:错误:无法将'int'左值绑定到'int&&'测试t(i);^main.cpp:7:5:注意:初始化'test :: test(T&&)[with T = int]'的参数1测试(T& t)^ ~~~

Error from GCC 5.2: main.cpp: In function 'int main()': main.cpp:20:18: error: cannot bind 'int' lvalue to 'int&&' test t(i); ^ main.cpp:7:5: note: initializing argument 1 of 'test::test(T&&) [with T = int]' test(T&& t) ^~~~

有人可以解释为什么类模板不能编译但是功能模板可以吗?谢谢.

Could someone explain why the class template cannot compile but function template is OK? Thanks.

推荐答案

您的困惑可能源于您在两种情况下 T int 的假设.这就是为什么您认为这两种情况相似.实际上不是.

Your confusion is probably rooted in your assumption that in both cases T is int. This is why you presume that these two cases as similar. In reality they are not.

在类版本中,您手动指定 T 是什么.您明确告诉编译器 T int .在这种情况下,构造函数参数类型 T& 变为 int& ,它不能绑定到常规左值.因此是错误.

In the class version you are manually specifying what T is. You explicitly tell the compiler that T is int. Constructor parameter type T && in this case becomes int &&, which cannot bind to a regular lvalue. Hence the error.

在函数版本中,您没有告诉编译器 T 是什么,而是希望编译器推断.在像您这样的情况下,该语言被故意设计为将 T 推导出为 int& (注意:不是 int ,而是int& ).一旦将 T 推导出为 int& ,即所谓的导致函数参数类型 T& 变为 int& -普通的左值引用.此参数可以成功绑定到左值参数 i .

In the function version you don't tell the compiler what T is, but instead you expect the compiler to deduce it. In situations like yours the language is deliberately designed to deduce T as int & (note: not as int, but rather as int &). Once T is deduced as int &, the so called "reference collapsing" rules lead to function parameter type T && becoming int & - an ordinary lvalue reference. This parameter can successfully bind to lvalue argument i.

这说明了您观察到的差异.

That explains the difference you observe.

为便于实验,在后一种情况下,您可以禁止模板参数推导并显式指定模板参数

For the sake of experiment, in the latter case you can suppress template argument deduction and specify the template argument explicitly

succeed<int>(i); 

由于相同的原因,这将强制将 T 指定为 int ,并导致与类版本中相同的错误.

That will forcefully specify T as int and lead to the very same error as in the class version for the very same reason.

类似地,您可以通过将模板参数指定为 int&

Similarly, you can "simulate" function's behavior for your class by specifying the template argument as int &

test<int &> t(i);

相同的引用折叠"规则将使您的构造函数调用成功编译.

The same "reference collapsing" rules will make your constructor invocation to compile successfully.

这篇关于类模板与函数模板中的右值引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆