是否所有使用指令的方式与使用命名空间std的方式相同

Are all using directives viewed the same way as using namespace std?

本文关键字:命名空间 std 方式相 方式 指令 是否      更新时间:2023-10-16

我很容易养成了用std::作为标准标识符前缀的习惯,而不是拘泥于using namespace std;。然而,我已经开始进入C#,我注意到添加任何必要的使用指令都是非常正常的,即,你会看到:

using System;
Console.Write("foo");

而不是:

System.Console.Write("foo");

显然,正如我在这个主题的C#问题中发现的那样,这种用法来自于这样一个事实,即C#中的单个系统名称空间比C++中的std小得多,因此消除了与名称冲突相关的问题,因为这种可能性要小得多(如果库更新时名称冲突,您可以找到用完全限定的名称替换它),并消除了与出现的Intellisense选项碎片负载相关的问题,因为命名空间足够小,可以处理。

那么,问题是,如果这些是在C#中使用指令的长期理由,那么C++也是如此吗?将其应用于较小的第三方名称空间以及您自己的较小名称空间通常是可以接受的吗?

现在我意识到这可能会引起一些争议,我想借此机会要求不要把它变成一场争论。一个好的答案应该包括一个基础,即优势或劣势,以及使用一种方式而不是另一种方式是如何真正产生有价值的差异的。

我这样做的原因是为了澄清这个问题,并可能消除在C++中使用指令一定是坏事的想法。当然,如果必要的话,可以使用命名空间别名来减少较长的命名空间名称,如果需要的话,仍然可以使用完全限定的名称,但有时使用using指令可以极大地简化访问一些成员,如用户定义的文字运算符,据我所知,这些运算符没有ADL的形式,这意味着你要么必须使用using指示,要么通过函数语法调用运算符方法,首先就破坏了使用运算符的全部目的。

例如,我有一个名称空间(包括一个表示键盘键的结构,以及一个文字后缀作为可读的替代访问方式:

"caps lock"_key.disable();

这里的问题是,除非您之前插入了using namespace Whatever;using Whatever::operator"" _key;,否则代码不会编译,这对用户来说是个坏消息。

当涉及std时,或者当在标头中以这样的方式使用指令时,使用指令会给该标头的用户带来不需要的额外内容,那么当指令包含在比包含标头的范围更小的范围内时,将其用于其他名称空间是否合理?不必每次都键入每个限定符所节省的键击确实会累积起来,而且利用今天的Intellisense功能,找出不合格标识符属于哪个命名空间就像鼠标悬停在它上面一样容易。

我认为在C++中使用声明的规则相当简单:

  1. 永远不要在标头的全局范围中写"使用命名空间任何东西;",尤其是可能被其他程序重用的标头(例如,在编写库时)。它用这个名称空间的符号污染了所有后续标头的全局范围,这违背了名称空间的全部用途,并可能在以后产生不可预见的名称冲突
  2. 在.cpp文件和头的内部作用域(例如内联函数作用域)中,您可以"使用"任何您想要的名称空间,因为它不会影响任何其他文件。只要做任何对你来说更方便的事情,并在项目中保持合理的一致性

EDIT:对于_key问题,只需在其自己的命名空间中定义此运算符,并告诉用户导入它。这样他们就不需要键入运算符声明。

namespace something {
class key { ... };
}
namespace key_suffix {
something::key operator"" _key() { ... }
}
// user code
void some_function() {
    using namespace key_suffix;
    "caps lock"_key.doSomething();
}