今天有人在 SO 上断言,你永远不应该在头文件中使用匿名命名空间。通常这是正确的,但我似乎记得曾经有人告诉我,其中一个标准库在头文件中使用匿名命名空间来执行某种初始化。
我没记错吗?有人可以填写详细信息吗?
今天有人在 SO 上断言,你永远不应该在头文件中使用匿名命名空间。通常这是正确的,但我似乎记得曾经有人告诉我,其中一个标准库在头文件中使用匿名命名空间来执行某种初始化。
我没记错吗?有人可以填写详细信息吗?
标头中的无名命名空间有用的唯一情况是您只想将代码作为头文件分发。例如,Boost 的一个大型独立子集纯粹是标头。
另一个答案中提到的元组令牌ignore
是一个示例,_1
等_2
绑定占位符是其他的。
我认为将匿名名称空间放入头文件中没有任何意义。我已经找到了标准和 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
这样你就可以做到
std::tie(a, std::ignore, b) = some_tuple;
some_tuple 的元素被分配了左侧的变量(参见此处),此迭代器使用了类似的技术。第二个元素被忽略。
但正如他们所说,它应该被放入一个 .cpp 文件中,并且一个实例应该由所有用户共享。他们会像这样在标题中声明它:
extern _Swallow_assign ignore;
我已经看到它用于为不同翻译单元中的变量提供默认值。但在名称冲突的情况下,它可能会导致意外行为。
例子
一个.hpp
namespace
{
const char name[] = "default";
}
// This macro will hide the anonymous variable "name"
#define SET_NAME(newname) \
static const char name[] = newname;
b.cpp
#include "a.hpp"
SET_NAME("file b") // name is "file b" in this translation unit
cpp
#include "a.hpp"
SET_NAME("file c") // name is "file c" in this translation unit
d.cpp
#include "a.hpp"
// name is "default" in this translation unit
e.cpp
#include "a.hpp"
static const char name[] = "unintended";
// accidently hiding anonymous name
我真的看不出在标题中使用匿名命名空间没有任何积极的好处。具有相同符号声明可能导致的混乱意味着,本质上,包含该标头的编译单元中的不同事物将是一种过早且痛苦地秃顶的保证方式。
如果它是初始化,它可能是一个iostream
s 标头(如istream
,ios
等)。