今天有人断言,你永远不应该在头文件中使用未命名的名称空间。通常这是正确的,但我似乎记得曾经有人告诉我,其中一个标准库在头文件中使用未命名的名称空间来执行某种初始化。
我没记错吗?有人可以填写详细信息吗?
头文件中的无名命名空间唯一有用的情况是当您只想将代码作为头文件分发时。例如,Boost 的一个大型独立子集纯粹是标头。
另一个答案中提到的元组标记
ignore
就是一个例子,_1
、_2
等绑定占位符是其他。
我认为将匿名名称空间放入头文件中没有任何意义。我已经 grep 标准和 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 的元素被分配左侧的变量(参见here),类似的技术也用于this迭代器。第二个元素被忽略。
但正如他们所说,它应该放入一个 .cpp 文件中,并且一个实例应该由所有用户共享。他们会将其声明放入标题中,如下所示:
extern _Swallow_assign ignore;
我见过它用于为不同翻译单元中的变量提供默认值。但在名称冲突的情况下可能会导致意外行为。
示例
a.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
c.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
标头(如 istream
、ios
等)。