是否允许为标准库类型和内置类型重载 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::string
和 int
之间重载 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.
即使是标准库中的类型,也可以在您的命名空间中定义它们。
当不存在这样的重载时,是否允许重载运算符,例如 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::string
和 int
之间重载 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.
即使是标准库中的类型,也可以在您的命名空间中定义它们。