模板参数的引用变量引起的问题

时间:2010-08-22 17:27:44

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

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

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):

  

错误:'静态空X :: xxx(T&amp;&amp;)[带T = int&amp;]'不能超载
  错误:'static void X :: xxx(T&amp;)[with T = int&amp;]'

为什么呢? T = int& ---&gt; T&中的int&&取代了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)'的匹配函数   注意:候选人是:static void X :: xxx(T&amp;)[with T = int&amp;]

T& T = 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; } 且不是右值参考。但如果不是,为什么第一个例子不起作用? (这是一个递归问题!)


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

{{1}}

为什么这种行为的参考不同?

1 个答案:

答案 0 :(得分:10)

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

  

如果typedef,类型 template-parameter decltype-speci fi er 表示类型TR,它是对类型{{1}的引用},

     
      
  • 尝试创建类型“对 cv T的左值引用”会创建“TR的左值引用”
  •   
  • 尝试创建“ cv T的rvalue引用”会创建类型TR
  •   

让我们考虑一下您的示例(我已将您的TR重命名为T,使其与上述语言相符):

TR

如果我们尝试使用template<class TR> struct X { static void xxx(TR& x) { } static void xxx(TR&& x) { } }; X)实例化TR = int&T = int的实例化如下:

xxx

在第一种情况下,我们尝试创建一个“static void xxx(TR& x) { } --> static void xxx(int& x) { } static void xxx(TR&& x) { } --> static void xxx(int& x) { } 的左值引用”,它将成为“TR的左值引用”。 TT,因此参数类型为int

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

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