是否有任何方法可以阻止命名空间在c++中添加更多的类?

Is there any way I can prevent a namespace from adding further classes in C++?

本文关键字:添加 c++ 命名空间 方法 任何 是否      更新时间:2023-10-16

我想创建一个名称空间,并防止它添加任何更多的类或其他东西。我有什么办法可以做到吗?

.​​​​​​​​​​​​​​​​​​​​​​​​​​​

@LightnessRacesinOrbit的回答是以下引用自标准

7.3名称空间(basic.namespace)

1名称空间是一个可选命名的声明性区域。可以使用命名空间的名称进行访问在该命名空间中声明的实体;的成员名称空间。与其他声明性区域不同,命名空间可以拆分为一个或多个翻译的几个部分单位。

因为翻译单元的数目是一个开放集合,所以命名空间的隶属关系是开放的。

然而,正如@Galik所建议的,您可以通过编写仅包含静态成员函数的结构或类来不完美地模拟封闭命名空间

struct closed_namespace {
static void fun() { /* bla */ }
};

名称空间到结构体的转换可能不是100%插入式的。例如,普通的名称查找可能会起到相同的作用,但您总是需要限定函数,因此ADL将被排除在外。

但调用代码几乎相同(即使用::访问器)

closed_namespace::fun();

,你也可以使用类型定义来缩短长名称,c++ 11 using语法类似于从左到右命名空间别名

using cn = closed_namespace;

另一方面,using指令和声明不能结转。

没有语言支持。这就是为什么您可以通过添加不应该添加的东西(如type_traits专门化)来混淆std名称空间。

我觉得不太需要这么做,因为如果我真的想的话,我可以通过简单地编辑源文件来做到这一点,但这并不是一个真正有意义的破坏程序的方法。

考虑到namespace s可以被多个tu扩展,那么您如何选择应该"终止"哪个名称空间呢?你能这样做吗,在某个点上它变得有问题,你goto前一段

我同意这是一个简单的布尔答案,真的不需要进一步的阐述,除了我们所有人都在说"我也是"或"不,你需要更啰嗦"。有时简洁是好的(并回答问题)。然而…

如果你想一下,这将是一个巨大的变化,整个工具链来执行这一点。元数据根本没有(如果有的话)保存在正确的位置,因此鼓励/需要(?为IP保护,但开源的人不会关心!)头文件(声明)和源体(实现)之间的分离会使编译器供应商更加混乱。我怀疑它根本不会获得任何牵引力,因为除非(即使没有)你让每个供应商/项目注册一个命名空间或使用一个UUID,否则冲突的可能性就太大了。

// <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 {
}
}
}
}

[begin soap box mode]在我使用过的项目中,人们已经做了大量的名称空间嵌套,这种东西很快就会过时。感谢c++ 11的使用(尽管没有模板<>的好处,类型定义几乎可以得到相同的东西)。

// 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列"标准"也会使成员声明变得痛苦。[结束soap_box_mode]

所以,就在这里吐槽吧。即使它是可行的。(从技术上讲,这只是一个挑战。)你愿意这样做吗?(那些从Java或c#开始的人可能已经习惯了这种风格,没有它似乎很痛苦。)我不讨厌它,但是要强制使用c++的所有历史遗产是很困难的。头文件定义ABI(应用程序二进制接口)的想法已经深深植根于C和c++标准中,并且除了声明之外还有大量的尾部。

在大多数情况下,名称空间是一种"幸运的hack"(在我看来,但仍然很有创意!),因为它们真的"只是"改变了初始编译(以及随后的编译/链接)期间的名称混乱,而不是其他。