我想创建一个命名空间,并阻止它添加任何更多的类或其他东西。我有什么方法可以实现这一点。
答案 0 :(得分:20)
没有
答案 1 :(得分:8)
@LightnessRacesinOrbit的答案由以下标准引用解释
7.3命名空间[basic.namespace]
1命名空间是可选命名的声明性区域。命名空间的名称可用于访问 在该命名空间中声明的实体也就是说,成员 命名空间。与其他声明性区域不同,a的定义 命名空间可以拆分为一个或多个转换的几个部分 单元。
由于翻译单元的数量是一个开放集,因此可以添加名称空间成员资格。
但是,正如@Galik所建议的那样,通过编写只包含静态成员函数的结构或类,您可以不完美地模拟一个封闭的命名空间
struct closed_namespace {
static void fun() { /* bla */ }
};
将命名空间转换为struct可能不是100%的插件。例如。普通名称查找可能行为相同,但您始终需要对函数进行限定,以便ADL离开窗口。
但调用代码几乎相同(即使用::
访问者)
closed_namespace::fun();
你也可以使用typedef来缩短使用C ++ 11 using
的长名称 - 类似于从左到右命名空间别名的语法
using cn = closed_namespace;
另一方面,使用指令和声明不会延续。
答案 2 :(得分:4)
没有语言支持。这就是为什么你可以添加std
命名空间来添加你不应该的东西,比如type_traits
专业化。
我真的不太需要这样做,因为如果我真的想要,我可以通过简单地编辑源文件来做到这一点,但这并不是打破程序的真正有益的方式。
考虑到namespace
可以被多个TU扩展,那么如何选择命名空间应该"终止"?你能做到这一点,并且在某些时候它会成为问题,你goto
上一段。
答案 3 :(得分:1)
我同意这是一个简单的布尔答案,真的不需要进一步阐述,除非我们所有人都在“我也是”或“不,你需要更加冗长”。有时简洁是好的(并回答问题)。然而...
如果你想一下它,那么对整个工具链来说,实施这一目标将是一个巨大的变化。元数据根本没有保留(如果有的话)在这个地方〜鼓励/需要(?对于知识产权保护可能,但是开源人员不关心!)标题之间的分离(声明)和源体(实现)会使编译器供应商变得更加混乱。我怀疑它不会获得任何牵引力因为除非(甚至不是)你使每个供应商/项目注册一个名称空间或使用UUID(yick),否则冲突的可能性太大了。
// <header1>
// Yick! (IMO)
namespace frozen std_A1DD3D0F_DC56_41D4_9B87_F820B420A94D
{
class foo { ... };
}
// <header2>
// Now what?
namespace frozen std_A1DD3D0F_DC56_41D4_9B87_F820B420A94D
{
class bar{ ... };
}
// Uh, Java like maybe?
namespace frozen com_google_fabulous_stuff_v1
{
// Yipes! This could get extra tricky
namespace thawed other_nested_junk
{
struct PainfulToUse
{
};
}
}
// Would this even make sense?
namespace frozen WizzyTool {
namespace thawed Module_Like_DLL_so_or_static_lib {
namespace frozen SeparateOptionalSubLibraryFromAnotherHeader {
namespace frozen ExtraSubSubLibraryNeededONLYForAdvancedUsers {
}
}
}
}
[开始肥皂盒模式] 在使用了人们完成命名空间主要嵌套的项目后,这种东西很快变得非常老旧。谢天谢地使用C ++ 11(尽管typedef几乎可以获得相同的东西,没有模板&lt;&gt; goodness)。
// Promote JUST the class_name into the scope Likely a method,
// 'translation unit', class body or function.
//
template<typename x1,typename x2>
using mapish = Some::Really::Deeply::Nested::mapish<x1,x2>;
// or in some cases this is nice:
template<typename x1>
using mapish_int = Some::Really::Deeply::Nested::mapish<x1,int>;
mapish_int<bool>::iterator x = ...
或
// Way too much typing and (IMO) harder to read.
// Counter argument is that the explicit scoping makes maintenance easier.
// Wanna debate tabs v spaces too?
Some::Really::Deeply::Nested::class_name<bool,int>::iterator x = ...
一个未命名的供应商使用第二种技术的一个特定项目将产生许多功能,即使是一个慷慨的120列“标准”也会使成员声明变得痛苦。 [end soap_box_mode]
所以,只是在这里吐痰。即使它是可以做到的东西。 (从技术上讲,这只是一个挑战。)你想要做到这一点吗? (那些以Java或C#开头的人可能已经习惯了这种风格,没有它看起来很痛苦。)我不厌恶它,但是很难强制执行 C ++的历史遗产。标题DEFINING ABI(应用程序二进制接口)的想法很好地嵌入到C和C ++标准中,并且在声明之外有一个巨大的尾巴。
在大多数情况下,命名空间是一个“幸运的黑客”(IMO,但仍然很有创意!),因为他们真的“只是”在初始编译(以及后续的编译/链接)中更改名称错误而没有其他内容。