摘自《Extended STL》中译
C++关键字namespace提供的名字空间是开放的:你可以在任何时候扩展其中的内容。只要另外声明一个同名的名字空间即可。但如此一来事态的发展可能完全出乎原作者的预料。例如,你可能写下这样的代码,指望用户对其中的名字空间敬若神明。
// OstensiblyDefinitiveVersion.hpp
namespace covenant
{
int func(std::string const& s); // Specific version for std::string
template <typename S>
int func(S const& s); // General version for other types
} // namespace covenant
但是用户可以改变covenant名字空间并带来潜在的破坏性后果,而我们对此却束手无策。
// CavalierManipulations.hpp
namespace covenant
{
int func(std::exception const& x);
} // namespace covenant
现在函数模板的适用范围缩小了,以前那些完全依赖旧版名字空间的代码会受到影响,或许它们的行为已经发生了变化。一般而言这不是什么好事,也说明了为什么C++标准只允许在一种情况下扩展std名字空间,即把std名字空间业已存在的模板完全特化后再加入进去。
为得到真正封闭的名字空间,你需要使用class/union/struct,就像这样:
// EnforceablyDefinitiveVersion.hpp
struct covenant
{
private:
covenant(); // Prevent construction: it is a "namespace" after all
public:
static int func(std::string const& s);
template <typename S>
static int func(S const& s);
}; // "namespace" covenant
上
面这样的"名字空间"和真正的名字空间相比,还受到一些额外的限制。例如它无法定义任何非整数类型的成员常量。同时也不能声明成员名字空间,而只能用内嵌
的class/struct/union来模拟。但除了具备封闭性外,还有一些优点也是名字空间不具备的,例如它允许定义私有成员以及友元,由此将其成员
的访问权限限定在一个已知的上下文中。
提示
用结构体来构造封闭的名字空间(当然得定义私有的构造函数)。
(转载请注明来源于金庆的专栏)