为了优雅,封装和利用ADL(Argument Dependent Lookup)在函数参数的命名空间内定义函数是很常见的。
假设我在不同的命名空间中有两个库。有三种情况1)一个是我控制的库的一部分,另一个是第三方(例如Boost),或者2)我控制两者,或者3)我控制没有(只是写"胶水"码)。
我有类似的东西,
namespace ns_A{
struct A{...}; // something that looks like iostream
}
namespace ns_B{
struct B{...};
}
我想" stream" 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<<;
}
哪个是定义像这样的二进制函数的最佳命名空间?
(C ++ 11和命名空间内联是否会改变任何建议?)
(我使用示例operator<<
因为,在其他条件相同的情况下,似乎直观地更喜欢namespace ns_B
。)
编辑:这是我在命名空间的实际使用中可以找到的最完整的指南和参考 https://www.google.com/amp/s/akrzemi1.wordpress.com/2016/01/16/a-customizable-framework/amp/
答案 0 :(得分:5)
在案例1中,很容易:将其放在您控制的namespace
中。
在案例2中,它取决于您的选择:无论什么看似更合乎逻辑。在您的示例中,我更喜欢ns_B
。
唯一棘手的情况是3.你不应该真正添加namespace
。如果你想要新的胶水&#39;功能作为您自己的第三个namespace mine
的一部分,然后自然地将其放在那里,mine
中对该功能的任何使用都将自动解决。当然,这不会占用ADL,但不需要它,因为您只需要在mine
内使用新功能,而不是在其他地方。
答案 1 :(得分:4)
您可以将您的运算符放在任一名称空间中,它将起作用。作为最佳实践,请将其放在属于您的代码的命名空间中。
答案 2 :(得分:2)
我的建议:不要使用任何命名空间。 .closest('li')
中的代码本身并不知道ns_A
中存在任何内容 - 它不依赖于它;因此,ns_A
和ns_B
构造的代码不属于ns_A
。对称性ns_A
也是如此。
您的ns_B
应位于operator<<
和ns_A
中的“最不常见的命名空间”中,这可能不是命名空间(但如果ns_B
是ns_A
然后ns1::ns2
为ns_B
,然后使用ns1::ns3
)。
在我看来,强制代码进入名称空间并不明显属于它,并不优雅,从概念上打破了封装。至于ADL,我认为你不应该期望ns1
和ns_A
的“最不常见的命名空间”给你带来的东西。