Какое наилучшее пространство имен для двоичного оператора?
Для элегантности, инкапсуляции и использования 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
.