以下小例子显示了我的问题:
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}}
为什么这种行为的参考不同?
答案 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
的左值引用”。 T
为T
,因此参数类型为int
。
在第二种情况下,我们尝试创建一个“int&
的右值引用”,该引用变为TR
,即TR
。
两个重载的参数类型相同,因此错误。