临时成员和非成员操作员选择const-overload的区别

时间:2012-01-03 13:11:55

标签: c++ operator-overloading const

在回答this question时,我发现rvalue的重载分辨率与成员和非成员运算符之间的引用有一个有趣的区别。

给定两个非成员运算符,一个将left参数作为const传递,另一个作为非const传递,GCC 4.4.3和MSVC2010在使用rvalue调用时选择const版本。

但是,给定两个成员运算符,一个const和一个非const,两个编译器都选择非const版本。

我认为两个编译器都遵守这个标准,所以我很好奇为什么成员和非成员之间的const重载决议之间存在这种差异。请赐教:))

以下是一些代码来说明差异:

#include <iostream>

class C {
public:
    C(int i) { }

    /*
    C operator<<(C const &rhs) {
        std::cout << "member non-const" << std::endl;
        return *this;
    }
    C operator<<(C const &rhs) const {
        std::cout << "member const" << std::endl;
        return *this;
    }
    //*/
};

C operator<<(C &lhs, C const &rhs) {
    std::cout << "non-member non-const" << std::endl;
    return lhs;
}
C operator<<(C const &lhs, C const &rhs) {
    std::cout << "non-member const" << std::endl;
    return lhs;
}

int main() {
    // Will print:
    // "non-member const" when member operators are commented out
    // "member non-const" when members are uncommented
    C(5) << 6;
}

1 个答案:

答案 0 :(得分:2)

Rvalues无法绑定到引用到非const,因此只有free函数的reference-to-const重载才可行:operator<<(C(5), 6);

这不适用于成员运算符,它只是C(5).operator<<(6),而C - 对象不是函数参数。您必须说static_cast<const C &>(C(5)) << 6才能获得const版本,因为this的常量可区分两个成员运算符重载。

在成员函数和自由函数运算符都存在的情况下,成员函数是首选,因此将所有这些放在一起就可以解释观察到的行为。