【发布时间】:2010-04-01 22:44:08
【问题描述】:
困扰我一段时间的事情:
目前的观点是类型应该保存在一个命名空间中, 包含属于该类型的非成员接口的函数(请参阅 C++ 编码标准 Sutter 和 Alexandrescu 或 here),以防止 ADL 引入不相关的定义。
这是否意味着所有类都必须有自己的命名空间?如果 我们假设一个类在未来可能会通过添加 非成员函数,那么将两种类型放在 与它们中的任何一个相同的命名空间都可能引入非成员函数 这可能会干扰对方。
我问的原因是命名空间对我来说变得很麻烦。我是 编写一个仅限标头的库,我发现自己使用类名称,例如 项目::组件::类名::类名。他们的实现调用 辅助函数,但因为它们不能在同一个命名空间中,所以它们也有 完全合格!
编辑:
一些答案表明,C++ 命名空间只是一种避免名称冲突的机制。事实并非如此。在 C++ 中,接受参数的函数使用 Argument Dependent Lookup 解析。这意味着当编译器试图找到与函数名称匹配的函数定义时,它会在寻找候选对象时查看 与其参数类型相同命名空间中的每个函数强>.
这可能会产生意想不到的、令人不快的后果,详见A Modest Proposal: Fixing ADL。 Sutter 和 Alexandrescu 的规则状态永远不会将函数放在与类相同的命名空间中,除非它是该类接口的一部分。除非我准备好为每个类提供自己的命名空间,否则我不明白如何才能遵守这条规则。
欢迎提出更多建议!
【问题讨论】:
-
“它们的实现调用必须完全限定的辅助函数” - 如果有帮助的话,您可以在函数体中放置
using声明或指令。 -
出于对所有神圣事物的热爱,不要在类和命名空间之间强制执行 1:1 的比例。破坏了拥有命名空间的全部目的,并导致大量额外的工作。
-
@James D:我不同意。我认为这还远远不够。我们还需要确保每个命名空间本身都在一个命名空间中。
-
那么告诉我,将
void foo(int)放在与class bar;相同的命名空间中究竟有什么危害? ADL究竟是如何给我们带来任何问题的? -
@jalf 如果我对 Sutter 的理解正确,当将
bar传递给函数void baz(bar b)时,baz的实现会从bar中引入 all 函数的命名空间。如果baz碰巧调用了一个名为foo的东西,而void foo(int)碰巧比它之前的匹配更好,那么它选择了错误的foo!
标签: c++ namespaces coding-style