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

Is it allowed to overload operator+ for a standard library type and a built-in type?

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

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

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

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

For example, is it legal to implement the following operator in the default namespace or a user-defined namespace:

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

是的,这样做是完全合法的。唯一的限制是关于向 namespace std 添加名称或专门化成员函数模板或 class 模板或为 std 中的 class 模板添加推导指南。

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

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
    }
}

这样写是合法的。但它不一定会如你所愿。

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

The set of non-member candidates is the result of the unqualified lookup of operator@ in the context of the expression according to the usual rules for name lookup in unqualified function calls (6.4.2) except that all member functions are ignored. However, if no operand has a class type, only those non-member functions in the lookup set that have a first parameter of type T1 or “reference to cv T1 ”, when T1 is an enumeration type, or (if there is a right operand) a second parameter of type T2 or “reference to cv T2”, when T2 is an enumeration type, are candidate functions.

但是由于您的 operator+ 不是 在与任一参数相同的名称空间中,ADL 查找将失败。而且非成员候选列表不会自动包含全局函数,它没有机会找到合适的 operator+.

所以你不能有效地重载这样的运算符而不打开命名空间。 std.

当然禁止哪个

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

An operator function shall either be a non-static member function or be a non-member function and have at least one parameter whose type is a class, a reference to a class, an enumeration, or a reference to an enumeration.

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