C++ 带有ref限定符的重载解析

C++ 带有ref限定符的重载解析,c++,c++11,overloading,language-lawyer,ref-qualifier,C++,C++11,Overloading,Language Lawyer,Ref Qualifier,在处理ref限定函数重载时,我从GCC(4.8.1)和Clang(2.9和trunk)中得到了不同的结果。考虑下面的代码: #include <iostream> #include <utility> struct foo { int& bar() & { std::cout << "non-const lvalue" << std::endl; return _bar; }

在处理ref限定函数重载时,我从GCC(4.8.1)和Clang(2.9和trunk)中得到了不同的结果。考虑下面的代码:

#include <iostream>
#include <utility>

struct foo
{
    int& bar() &
    {
        std::cout << "non-const lvalue" << std::endl;
        return _bar;
    }
    //~ int&& bar() &&
    //~ {
    //~     std::cout << "non-const rvalue" << std::endl;
    //~     return std::move(_bar);
    //~ }
    int const& bar() const &
    {
        std::cout << "const lvalue" << std::endl;
        return _bar;
    }
    int const&& bar() const &&
    {
        std::cout << "const rvalue" << std::endl;
        return std::move(_bar);
    }

    int _bar;
};

int main(int argc, char** argv)
{
    foo().bar();
}
#包括
#包括
结构foo
{
int&bar()&
{

std::cout首先,根据13.3.1.4,隐式对象参数被视为正常参数:

对于非静态成员函数,隐式对象参数的类型为

-对于不使用ref限定符或使用&ref限定符声明的函数,“对cv X的左值引用”

-使用&&ref限定符声明的函数的“对cv X的右值引用”

其中,X是该函数所属的类别,cv是该成员的cv资格 函数声明

因此,您的问题相当于以下内容:

void bar(foo&);
void bar(foo&&);
void bar(const foo&);
void bar(const foo&&);

int main()
{
    bar(foo());
}
表达式
foo()
是一个类值

其次,非常量左值引用版本是不可行的,因为prvalue不能绑定到它

这就给我们留下了三个解决过载问题的可行函数

每个都有一个隐式对象参数(
const foo&
foo&
const foo&&
),因此我们必须对这三个参数进行排序,以确定最佳匹配

在这三种情况下,它都是直接绑定的引用绑定。这在declarators/initialization(8.5.3)中有描述

三种可能绑定(
const-foo&
foo&
const-foo&
)的排名如13.3.3.2.3所述:

标准转换序列S1是比标准转换序列S2更好的转换序列

  • S1和S2都是引用绑定,都不引用未声明ref限定符的非静态成员函数的隐式对象参数[此异常不适用于此处,它们都有ref限定符],S1将右值引用绑定到右值。[class prvalue是右值]和S2绑定左值引用
这意味着
foo&
const foo&
都比
const foo&

  • S1和S2是引用绑定,引用所引用的类型除了顶级cv限定符外都是相同的类型,并且由S2初始化的引用所引用的类型比由S1初始化的引用所引用的类型更符合cv限定
这意味着
foo&
优于
const foo&

所以Clang是对的,它是GCC中的一个bug。
foo().bar()
的重载排名如下:

struct foo
{
    int&& bar() &&;             // VIABLE - BEST  (1)
    int const&& bar() const &&; // VIABLE -       (2)
    int const& bar() const &;   // VIABLE - WORST (3)
    int& bar() &;               // NOT VIABLE

    int _bar;
};

GCC中的错误似乎完全适用于隐式对象参数(使用
ref限定符
),对于一个普通参数,它似乎得到了正确的排名,至少在4.7.2中是这样。

右值引用在所有情况下都是更好的匹配。这可能是GGC的ref限定符的一个错误。此外,可能是相关的。;)谢谢你的详细回答。我希望我能多次投票!