用于头文件中的匿名名称空间

Dav*_*man 50 c++ namespaces initialization header

今天有人断言你绝不应该在头文件中使用匿名命名空间.通常这是正确的,但我似乎记得有人告诉我,其中一个标准库在头文件中使用匿名命名空间来执行某种初始化.

我记得没错吗?有人可以填写详细信息吗?

Jam*_*kin 26

标头中无名称空间可能有用的唯一情况是,您只想将代码分发为头文件.例如,Boost的一个大型独立子集纯粹是标题.

ignore另一个答案中提到的元组令牌是一个例子_1,_2等等绑定占位符是其他的.

  • @thehouse这是一个允许只有头文件库提供全局对象的技巧,这通常会导致链接错误.将对象放在匿名命名空间中会强制每个编译单元创建自己的实例.在_1,_2等情况下,多个实例无关紧要,因为它们是无状态的.另一种实现相同效果的方法是使用模板类的静态成员,但是客户端必须输入类似Dummy <> :: _ 1而不仅仅是_1的内容. (11认同)
  • 定义 `_1`、`_2`、`ignore` 等的最先进方法是使用 `inline` 变量。 (5认同)
  • 您不应该为此使用匿名命名空间,因为它们在最终编译单元中全部折叠在一起,可能会导致命名空间冲突。相反,按照惯例,使用的名称意味着内容是实现细节。例如,Boost 使用“detail”。 (2认同)
  • @thehouse你似乎误解了Boost如何使用匿名命名空间。`ignore` 和 `_1`、`_2` 等是公共符号 - 它们不属于 `detail`。但我同意,详细名称空间通常是相当于匿名名称空间的头库的正确选择。 (2认同)
  • @JamesHopkin 总是乐于学习。你能解释一下为什么 _1 和 _2 位于匿名命名空间中而不仅仅是“命名空间 boost”中吗?这有什么好处? (2认同)

Joh*_*itb 15

我没有看到将匿名命名空间放入头文件中的任何意义.我已经使用了标准和libstdc ++标题,发现标题中没有一个匿名名称空间tuple(C++ 1x内容):

  // A class (and instance) which can be used in 'tie' when an element
  // of a tuple is not required
  struct _Swallow_assign
  {
    template<class _Tp>
      _Swallow_assign&
      operator=(const _Tp&)
      { return *this; }
  };

  // TODO: Put this in some kind of shared file.
  namespace
  {
    _Swallow_assign ignore;
  }; // anonymous namespace
Run Code Online (Sandbox Code Playgroud)

这是你可以做到的

std::tie(a, std::ignore, b) = some_tuple;
Run Code Online (Sandbox Code Playgroud)

some_tuple的元素在左侧分配变量(参见此处),迭代器使用了类似的技术.第二个元素被忽略.

但正如他们所说,应将其放入.cpp文件中,并且所有用户都应共享一个实例.他们会像这样在头文件中声明它:

extern _Swallow_assign ignore;
Run Code Online (Sandbox Code Playgroud)

  • @Johannes:你做了:-) (20认同)
  • 等等..现在我明白为什么他叫我悲观:)好的litb和其他一些悲观主义者称它为c ++ 1x.让我们看看谁将赢得赌注:p (4认同)

Jac*_*rto 6

我已经看到它曾经为不同翻译单元中的变量提供默认值.但在名称冲突的情况下,它可能会导致意外行为.

a.hpp

namespace
{
    const char name[] = "default";
}
// This macro will hide the anonymous variable "name"
#define SET_NAME(newname) \
static const char name[] = newname;
Run Code Online (Sandbox Code Playgroud)

b.cpp

#include "a.hpp"
SET_NAME("file b") // name is "file b" in this translation unit
Run Code Online (Sandbox Code Playgroud)

c.cpp

#include "a.hpp"
SET_NAME("file c") // name is "file c" in this translation unit
Run Code Online (Sandbox Code Playgroud)

d.cpp

#include "a.hpp"
// name is "default" in this translation unit
Run Code Online (Sandbox Code Playgroud)

e.cpp

#include "a.hpp"
static const char name[] = "unintended";
// accidently hiding anonymous name
Run Code Online (Sandbox Code Playgroud)