Classes and class hierarchies
C.168
Определяйте перегруженные операторы в пространстве имён их операндов
Причина
Читаемость кода. Возможность находить операторы через ADL. Предотвращение несогласованных определений в разных пространствах имён.
Пример
struct S { };
S operator+(S, S); // OK: в том же пространстве имён, что и S, и даже рядом с S
S s;
S r = s + s;
Пример
namespace N {
struct S { };
S operator+(S, S); // OK: в том же пространстве имён, что и S, и даже рядом с S
}
N::S s;
S r = s + s; // находит N::operator+() через ADL
Пример (плохой)
struct S { };
S s;
namespace N {
bool operator!(S a) { return true; }
bool not_s = !s;
}
namespace M {
bool operator!(S a) { return false; }
bool not_s = !s;
}
Здесь смысл выражения !s различается в N и M. Это может вызвать серьёзную путаницу. Уберите определение namespace M — и путаница заменяется возможностью совершить ошибку.
Примечание
Если бинарный оператор определён для двух типов из разных пространств имён, следовать этому правилу невозможно. Например:
Vec::Vector operator*(const Vec::Vector&, const Mat::Matrix&);
Возможно, лучше вообще избегать подобного.
Смотрите также
Это частный случай правила о том, что вспомогательные функции должны быть определены в том же пространстве имён, что и их класс.
Контроль
- Отмечать определения операторов не в пространстве имён их операндов.