是否允许为标准库类型和内置类型重载operator +?

时间:2017-11-22 20:12:19

标签: c++ operator-overloading language-lawyer user-defined-types

当这样的重载不存在时,是否允许重载运算符,例如operator+,以获得标准库类型和内置类型的组合?

例如,在默认命名空间或用户定义的命名空间中实现以下运算符是否合法:

std::string operator+(const std::string& s, int right) { ... }

我知道在 std::命名空间中实现的内容存在各种限制,但我不清楚是否有针对上述内容的规则(是否是个好主意)当然是完全不同的事情!)。

3 个答案:

答案 0 :(得分:3)

operator+std::string之间重载int是完全可以的。标准对此的唯一限制是(https://timsong-cpp.github.io/cppwp/n3337/over.oper#6):

  

运算符函数应该是非静态成员函数或者是非成员函数,并且至少有一个参数,其类型是类,对类的引用,枚举或对枚举的引用。

即使是标准库中的类型,也无法在命名空间中定义它们。

答案 1 :(得分:2)

  

例如,在默认命名空间或用户定义的命名空间中实现以下运算符是否合法:

std::string operator+(const std::string& s, int right) { ... }

是的,这样做是完全合法的。唯一的限制是将名称添加到namespace std或专门的成员函数功能模板或类模板,或者为std中的类模板添加演绎指南。

没有什么能阻止你写下这样的东西:

namespace N {
    std::string operator+(std::string s, int ) { return s; }
}

根据标准,这是一个结构良好的计划。但请注意,根据定义,您的运算符中不会包含任何程序定义的类型,ADL永远不会找到它们。由于它们是ADL常见的运算符,因此这本身可能是避免这种模式的原因:

namespace U {
    auto foo() {
        return "hello"s + 1; // error: name lookup doesn't find our operator
    }

    auto bar() {
        using namespace N;
        return "hello"s + 1; // ok: for some definition of ok
    }
}

答案 2 :(得分:2)

写这个是合法的。但它不一定能做你想做的事。

如果您的目标是制作some_string + 4合法的C ++代码,那么它的合法性将取决于该表达式的确切位置。运算符重载将使用ADL查找运算符[over.match.oper] /3.2:

  

非成员候选集是根据非限定函数调用(6.4.2)中通常的名称查找规则,在表达式上下文中对operator @进行非限定查找的结果,除了忽略所有成员函数。但是,如果没有操作数具有类类型,则只有那些非成员   查找集中具有第一个参数类型为T1或“引用到cv T1”的函数,当T1是枚举类型时,或者(如果有右操作数)第二个参数类型为T2或“引用到cv T2” ,当T2是枚举类型时,是候选函数。

但由于您的operator+ 与任一参数在同一名称空间中,因此ADL查找将失败。非会员候选人名单不会自动包含全球职能,因此没有机会找到合适的operator+

因此,如果不打开命名空间,就无法有效地重载此类运算符。当然禁止std