C++ 模板参数的引用变量导致的问题

C++ 模板参数的引用变量导致的问题,c++,templates,c++11,rvalue-reference,lvalue,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!

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

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(int)”时没有匹配的函数
注:候选项为:静态void X::xxx(T&)[带T=int&]

然后带
T=int&
T&
不等于
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;
}
#包括
模板结构X
{

静态void xxx(T*x){std::coutC++11语言标准在§8.3.2[dcl.ref]/6(为可读性重新格式化)中对其工作原理进行了解释:

如果typedef、类型模板参数或decltype specifier表示类型
TR
,它是对类型
T
的引用

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

让我们考虑你的例子(我把你的<代码> t>代码>改为<代码> Tr/代码>,这样它与上面的语言匹配):

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

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


对于两种过载,参数类型相同,对于两种过载,参数类型相同,因此错误。

我的头受伤,我的头受伤,这么多的人和和和和和&&

我的头受伤,我的头受伤,我的头受伤,我的很多的人和和和和和和和和和和和和和和和和和和&&&&&&&&和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和&&&&&&&&&&&&&&&&&&&&&&&&&和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和和&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&PEC完全支持表示TR的含义。这是使
std::forward
起作用的规则吗?也就是说,每个C++0x程序员都必须知道这一点…:)@UncleBens:这条规则不是用于右值引用的,它可以追溯到右值引用之前。在C++98中,“试图创建引用类型的引用”会导致类型推导失败(Pr.14.82/2)。它被提出,并且它的解析给出了这里所描述的行为(仅针对LValk引用)。我曾认为这个规则包含在C++ 03中(VC++和JuututIS在C++模板中是预期的)。,但事实并非如此。
forward
需要使用此规则才能工作。这种行为称为引用崩溃(我刚刚记住了这一点;我一整天都在发疯,因为我记不起它叫什么)。
#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;
}
template<class TR> struct X
{
    static void xxx(TR& x)  { }
    static void xxx(TR&& x) { }
};
static void xxx(TR& x)  { }   -->   static void xxx(int& x) { }
static void xxx(TR&& x) { }   -->   static void xxx(int& x) { }