M. *_* E. 4 c++ templates lvalue rvalue-reference c++11
以下小例子显示了我的问题:
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;
}
Run Code Online (Sandbox Code Playgroud)
错误消息(GCC):
错误:'static void X :: xxx(T &&)[with T = int&]'无法重载
错误:'static void X :: xxx(T&)[with T = int&]'
为什么?T = int&--->是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;
}
Run Code Online (Sandbox Code Playgroud)
错误消息(GCC):
错误:没有匹配函数来调用'X :: xxx(int)'
注意:候选者是:static void X :: xxx(T&)[with T = int&]
然后T&使用T = int&不等于T&&并且不是rvalue-reference.但如果不是,为什么第一个例子不起作用?(这是一个递归问题!)
但是指针类型没有出现类似的问题:
#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;
}
Run Code Online (Sandbox Code Playgroud)
为什么这种行为的参考不同?
Jam*_*lis 10
C++ 11语言标准在§8.3.2[dcl.ref]/6(为了可读性而重新格式化)中解释了它的工作原理:
如果typedef,type template-parameter或decltype-speci fi er表示作为类型
TR引用的类型T,
- 尝试创建类型"对cv的 左值引用
TR"创建类型"左值引用T"- 尝试创建"对cv的 rvalue引用
TR"类型会创建该类型TR.
让我们考虑你的榜样(我已经改名为你T要TR因此它的语言相匹配以上):
template<class TR> struct X
{
static void xxx(TR& x) { }
static void xxx(TR&& x) { }
};
Run Code Online (Sandbox Code Playgroud)
如果我们尝试X用TR = 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) { }
Run Code Online (Sandbox Code Playgroud)
在第一种情况下,我们尝试创建一个"左值引用TR",它成为"左值引用T". T是的int,所以参数类型变成了int&.
在第二种情况下,我们试图创建一个"右值参照TR",其变TR,这是int&.
两个重载的参数类型相同,因此错误.