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

时间:2012-09-04 03:55:40

标签: c++ coding-style using-directives

我很容易养成使用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指令,要么通过函数语法调用operator方法,首先要破坏使用运算符的整个目的。

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

"caps lock"_key.disable();

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

当涉及std或在标题中以这种方式使用指令时,使用指令会出现明显的问题,它们会为该标头的用户带来不必要的额外内容,但是当包含它时,将它们用于其他名称空间是合理的在比任何包括标题的范围更小的范围内?保存的键击不必每次都输入每个限定符,并且使用今天的Intellisense功能,找出非限定标识符所属的命名空间就像鼠标悬停一样容易。

1 个答案:

答案 0 :(得分:2)

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

  1. 永远不要写“使用命名空间任何东西;”在标题的全局范围内,尤其是可能被其他程序重用的标题(例如,在编写库时)。它使用此命名空间的符号来污染所有后续标头的全局范围,这会破坏命名空间的整个目的,并且可能会在以后创建无法预料的名称冲突。
  2. 在.cpp文件和标题的内部范围(例如内联函数范围)中,您可以“使用”您想要的任何名称空间,因为它不会影响任何其他文件。只做对你更方便的事情,并尝试在项目中保持合理的一致性。
  3. 编辑:对于_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();
    }