5

以下小示例显示了我的问题:

template<class T> struct X
{
    static void xxx(T& x) { }
    static void xxx(T&& x) { }
};

int main(int argc, char** argv)
{
    int x = 9;
    X<int>::xxx(x); // OK.
    X<int&>::xxx(x); // ERROR!
    return 0;
}

错误信息(GCC):

错误:'static void X::xxx(T&&) [with T = int&]' 不能重载
错误:with 'static void X::xxx(T&) [with T = int&]'</p>

为什么?T = int&--->T&替换为int&&in static void xxx(T& x)

如果问题的答案是肯定的,那么:

  • T&不是左值引用,而是成为右值引用!
  • 以下代码应该可以工作:

但它没有:

template<class T> struct X
{
    static void xxx(T& x) { }
};

int main(int argc, char** argv)
{
    X<int&>::xxx(2); // ERROR!
    return 0;
}

错误信息(GCC):

错误:没有匹配函数调用 'X::xxx(int)'<br> 注意:候选者是:static void X::xxx(T&) [with T = int&]

然后T&withT = int&不等于T&&并且不是右值引用。但如果不是,为什么第一个例子不起作用?(这是一个递归问题!)


但是指针类型没有出现类似的问题:

#include <iostream>

template<class T> struct X
{
    static void xxx(T* x) { std::cout << **x << std::endl; }
};

int main(int argc, char** argv)
{
    int x = 10;
    int* xx = &x;
    X<int*>::xxx(&xx); // OK. call X<int*>::xxx(int**)
    return 0;
}

为什么引用在这种行为中有所不同?

4

1 回答 1

10

C++11 语言标准在 §8.3.2[dcl.ref]/6 中解释了它是如何工作的(为了可读性而重新格式化):

如果 typedef、type template-parameterdecltype-specifier表示的类型TR是对 type 的引用T

  • 尝试创建类型“lvalue reference to cv TR ”会创建类型“lvalue reference to T
  • 尝试创建类型“对cv TR的右值引用”会创建类型TR

让我们考虑您的示例(我已将您重命名为TTR以便它与上面的语言匹配):

template<class TR> struct X
{
    static void xxx(TR& x)  { }
    static void xxx(TR&& x) { }
};

如果我们尝试XTR = int&(so, T = int) 进行实例化,则 的实例化xxx如下:

static void xxx(TR& x)  { }   -->   static void xxx(int& x) { }
static void xxx(TR&& x) { }   -->   static void xxx(int& x) { }

在第一种情况下,我们尝试创建一个“对 的左值引用TR”,它变成了一个“对 的左值引用T”。 Tint,所以参数类型变为int&

在第二种情况下,我们尝试创建一个“对 的右值引用TR”,它变为TR,即int&

两个重载的参数类型相同,因此出现错误。

于 2010-08-22T17:51:15.600 回答