为何T&&实例化为int&?

时间:2010-12-01 18:29:26

标签: c++ templates c++11 forwarding rvalue-reference

任何人都可以解释为什么这会编译,为什么t会以int&类型结束?

#include <utility>

void f(int& r)
{
    ++r;
}

template <typename Fun, typename T>
void g(Fun fun, T&& t) 
{ 
    fun(std::forward<T>(t)); 
}

int main()
{
    int i = 0;

    g(f, i);
}

我在GCC 4.5.0 20100604和GDB 7.2-60.2

上看到了这一点

2 个答案:

答案 0 :(得分:17)

由于完美转发,当P&&的参数为左值时,P将推断为参数的类型加上&。因此,当int & &&P时,您获得int&。如果参数是右值,则P将仅推导为参数的类型,因此获得int&&参数,其中Pint如果你愿意直接传递,例如0

int& &&将崩溃为int&(这是语义视图 - 语法int& &&是非法的。但U &&U是模板参数或一个typedef引用类型int&,然后U&&仍然是类型int& - 即两个引用“折叠”到一个左值引用)。这就是t类型为int&的原因。

答案 1 :(得分:3)

如果由于某种原因你真的想特别绑定到左值或右值,请使用元编程:

#include <type_traits>

template <typename T>
typename std::enable_if<std::is_lvalue_reference<T&&>::value, void>::type
fun(T&& x)
{
    std::cout << "lvalue argument\n";
}

template <typename T>
typename std::enable_if<std::is_rvalue_reference<T&&>::value, void>::type
fun(T&& x)
{
    std::cout << "rvalue argument\n";
}

int main()
{
    int i = 42;
    fun(i);
    fun(42);
}