Какое наилучшее пространство имен для двоичного оператора?

Для элегантности, инкапсуляции и использования ADL (Поиск зависимых аргументов) является общим для определения функции внутри пространства имен аргумента функции.

Предположим, у меня есть две библиотеки в разных пространствах имен. Есть три случая: 1) один из них является частью библиотеки, которую я контролирую, а другой - третьей стороной (например, Boost) или 2) я управляю обоими, или 3) я не контролирую ни одного (просто пишу "код клея" ).

У меня есть что-то вроде этого,

namespace ns_A{
   struct A{...}; // something that looks like iostream
}
namespace ns_B{
   struct B{...};
}

Я хочу "потопить" B в A, что является лучшим вариантом

namespace ???{ // what is more correct ns_A, or ns_B?
   A& operator<<(A& a, B const& b){...} 
}

или я должен помещать его в оба пространства имен?

namespace ns_B{
   A& operator<<(A& a, B const& b){...} 
}
namespace ns_A{
   using ns_B::operator<<;
}

Какое наилучшее пространство имен для определения такой бинарной функции?

(Является ли пространство имен С++ 11 встроенным?)

(Я использую пример operator<<, потому что, при прочих равных условиях, кажется интуитивно предпочтительнее namespace ns_B.)

Ответ 1

В случае 1 это легко: поместите его в namespace, который вы контролируете.

В случае 2 это зависит от вашего выбора: все, что кажется более логичным. В вашем примере, я бы предпочел ns_B.

Единственная сложная ситуация - 3. Нельзя добавить ни к namespace. Если вы хотите, чтобы новая функциональность "клей" была частью вашего третьего трека namespace mine, тогда, естественно, поместите ее туда, и любое использование этой функции в mine будет автоматически разрешено. Естественно, это не будет объявлять ADL, но в этом нет необходимости, поскольку все, что вам нужно, - это использовать новую функциональность в mine, а не где-то еще.

Ответ 2

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

Ответ 3

Мое предложение: Не используйте какое-либо пространство имен. Код в ns_A сам по себе не знает о существовании чего-либо в ns_A - он не зависит от него; поэтому код для конструкций ns_B и ns_A не относится к ns_A. То же самое верно для ns_B по симметрии.

Ваш operator<< должен находиться в "наименее распространенном пространстве имен" среди ns_A и ns_B, который, вероятно, не содержит пространства имен (но если ns_A is ns1::ns2 и ns_B is ns1::ns3, то используйте ns1).

Принудительный код в пространство имен, в котором он явно не принадлежит, по-моему, не изящно и не нарушает инкапсуляцию, концептуально. Что касается ADL, я думаю, вы не должны ожидать больше, чем дает "наименее распространенное пространство имен" ns_A и ns_B.