C ++如何在rvalue引用上进行模板推导?

时间:2014-10-16 00:16:27

标签: c++ templates rvalue-reference

template<typename T>
void foo(T&& arg);

我知道arg是否是左值,例如int x = 0; foo(x);然后T = int&,函数将是foo(int& &&),即foo(int&)

如果arg是右值,例如foo(0);然后是T = int,函数将是foo(int&&)

如果我有

怎么办?
template<typename T>
void foo(T& arg);

template<typename U>
void bar(U&& u)
{
    foo(u);
}

调用T时,foo中的bar(0)会是什么?

3 个答案:

答案 0 :(得分:3)

template<typename U>
void bar(U&& u)
{
    foo(u);
}

无论您传递给bar的是什么,u都是左值,因为它有一个名称。

u可能是左值参考或右值参考,但当您将其传递给foo时,其参考值为&#34;按照惯例被忽略。

暂时忘掉左值和右值和模板。对于另一个变量,引用应该是别名,并且在大多数情况下,引用按名称引用的行为应该就像引用原始变量一样:

int i = 42;
int& r = i;

f(int);
f(int&);
f(i); // error: call to ambiguous overload
f(r); // error: call to ambiguous overload

g(int);
g(r); // OK, pass by copy, reference-ness of r is irrelevant

h(int&);
h(i); // OK, pass by reference, non-reference-ness of i is irrelevant

在上面的函数调用语句中, id-expressions irint类型的左值。 变量 ir分别是非引用和引用的事实与相应 id-expressions的类型或值类别无关。这是引用始终有效的方式,并且右值引用不会改变它。

template<typename T>
void foo(T& arg);

没有任何内容可以传递给foo,这会使T成为引用类型。 arg始终是左值参考。

如果要传播参数的值类别,则需要std::forward

template<typename U>
void baz(U&& u)
{
    foo(std::forward<U>(u));
}

baz(42); // error: attempted to call foo() with an rvalue

答案 1 :(得分:0)

它应该是U最终的任何东西,所以如果U是一个int,它将是

bar(int&& u)
{
    foo(u);
}

将int传递给foo。

答案 2 :(得分:0)

  

如果我有

怎么办?
template<typename T>
void foo(T& arg);

template<typename U>
void bar(U&& u)
{
    foo(u);
}
  

调用bar(0)时foo中的T是什么?

听起来有点出乎意料,但是使用右值引用是左值表达式,这意味着u中的foo(u)左值,它是完全可以调用一个带左值引用的函数(在本例中为foo

也就是说,对于呼叫bar(0),使用的专业化将是:

bar<int>(int&&)
foo<int>(int&)

对于int value; bar(value);,专业化将是:

bar<int&>(int& &&) // i.e. int&
foo<int>(int&)