Где должны быть размещены перегрузки операторов, не являющихся членами?

Я хочу перегрузить operator<< для моего класса. Должен ли я добавить это перегруженное определение в пространство имен std? (так как ostream operator<< является частью пространства имен std). Или я должен просто оставить его в глобальном пространстве имен?

Короче:

class MyClass {

};

namespace std {
    ostream& operator<< ( ostream& Ostr, const MyClass& MyType ) {}
}

ИЛИ

class MyClass {

};

std::ostream& operator<< ( std::ostream& Ostr, const MyClass& MyType ) {}

Что более подходит и почему? Заранее благодарим за ваши ответы.

Ответы

Ответ 1

Вы должны перегрузить оператор в том же пространстве имен, что и ваш класс.

Это позволит оператору найти во время разрешения перегрузки, используя зависящий от аргумента поиск (ну, фактически, поскольку ostream находится в пространстве имен std, перегрузка перегрузки также будет найдена, если вы поместите ее в пространство имен std, но для этого нет оснований).

С точки зрения хорошей практики проектирования перегрузка оператора является скорее частью интерфейса вашего класса, чем интерфейсом ostream, поэтому она принадлежит к тому же пространству имен, что и ваш класс (см. также Herb Sutter Пространства имен и принцип интерфейса).

С точки зрения написания стандартно-совместимого и переносимого кода вы не можете перегрузить оператор в пространство имен std. Хотя вы можете добавлять специализированные шаблоны для определяемых пользователем объектов в пространство имен std, вы не можете добавлять дополнительные перегрузки функций.

Ответ 2

Не добавляйте к стандартному пространству имен. Причина. Если бы все это сделали, стандартное пространство имен имело бы кучи конфликтов имен, которые побеждают цель пространства имен.

Ваша цель состоит в том, чтобы ваш класс был "активным". Для этого не нужно находиться в стандартном пространстве имен. До тех пор, пока это объявлено в каком-либо объявлении вашего класса, вы в порядке. Включение его в стандартное пространство имен было бы плохой практикой.

Ответ 3

Не добавляйте его в пространство имен std, поместите его в том же пространстве имен, что и ваш класс. Цель пространства имен - предотвращать конфликты. В стандарте говорится

17.4.3.1 Зарезервированные имена

Это undefined для программы на С++. добавлять декларации или определения к пространства имен или пространства имен внутри пространство имен std, если иное указано. Программа может добавить шаблон специализации для любого стандарта шаблон библиотеки в пространство имен std. Такая специализация (полная или частичная) стандартной библиотеки результат шаблона в undefinedесли декларация не зависит от определяемое пользователем имя внешней связи и если специализация не встречается требования к стандартной библиотеке для исходный шаблон.