【问题标题】:Bad practice to declare names in the standard namespace?在标准命名空间中声明名称的坏习惯?
【发布时间】:2011-08-06 17:29:17
【问题描述】:

我正在浏览Google C++ style guide,发现了这个:

“不要在命名空间std中声明任何东西,甚至不要前向声明标准库类。在命名空间std中声明实体是未定义的行为,即不可移植。要从标准库中声明实体,请​​包含适当的头文件。”

有人可以使用示例代码解释这意味着什么以及为什么这是未定义的行为吗?

【问题讨论】:

    标签: c++ coding-style c++-standard-library


    【解决方案1】:

    他们说你不应该转发像这样声明标准库中的东西:

    // myheader.h
    namespace std{
    template<class T>
    void SomeStandardFunction();
    }
    
    // use std::SomeStandardFunction
    

    相反,您应该直接包含标题:

    // myheader.h
    #include <SomeHeaderThatContainsSomeStandardFunction>
    
    // use std::SomeStandardFunction
    

    【讨论】:

    • 缺少空格:模板 > 向量; (-:
    • @soul:更明显的问题是在allocator 之后缺少;,并且allocator 在用作模板参数之前需要完全定义,所以我更改了示例。 :)
    【解决方案2】:

    首先,就像许多 Google 风格指南一样,它实际上是错误的。该标准特别允许您在命名空间 std 中定义一些特定实体(例如,现有模板对用户定义类型的特化)。

    然而,忽略这些异常,它们确实有正确的总体思路——您的代码通常属于命名空间 std 之外的某个位置其他。你可以把它放在全局命名空间中,也可以定义另一个命名空间,但你应该不理会std

    您还应该尝试在标准库中前向声明任何内容。允许(例如)标准函数包含额外参数,只要它们包含默认值,因此可以以标准方式调用它们。如果您尝试自己声明它们,而不是声明现有函数,您最终可能会声明一个模棱两可的重载。

    底线:是的,使用标准库。当您使用它时,请通过包含标准标头而不是尝试编写自己的标头来获取声明。

    【讨论】:

    • +1 击败了我:“这实际上是错误的。......现有模板的专业化......”。专门化std::swap&lt;&gt;() 是一种常见且可接受的做法。
    • +1 表示“首先,就像 Google 风格指南的大部分内容,它实际上是错误的。”
    【解决方案3】:

    这并不是说“不要使用标准库”。

    使用某物和声明某物是两件不同的事情。它是说不要声明任何东西,就像不要做“class ostream;”之类的事情。我想人们过去必须这样声明才能使用它,但现在,由于东西是在命名空间 std 中声明的,你只需包含头文件。

    签出this

    【讨论】:

      【解决方案4】:

      有人可以使用示例代码解释这意味着什么以及为什么这是未定义的行为吗?

      以下程序产生未定义的行为:

      namespace std {
          void foo(int) { }
      }
      
      #include <iostream>
      
      int main() {
          std::cout << "Hello World!" << std::endl;
      }
      

      为什么?它在命名空间std 中声明了一个名为foo 的函数。至于为什么这会导致问题,请考虑:标准库实现可能有自己的名为foo() 的函数,并且可能被&lt;iostream&gt; 中的某些组件使用。你的foo 可能比标准库实现的foo 更匹配。

      【讨论】:

      • 除非我们专门从事std::swap&lt;&gt;()。我们被允许这样做。 :p
      • @wilhelmtell :即使这样也很糟糕。最好在与您的类型相同的命名空间中定义一个交换重载,并让 ADL 完成查找它的工作。
      • @wilhelmtell:你可以专门化 std模板;你不能overload std 模板。对于swap,正如@ildjarn 所说,首选的解决方案是使用可以通过ADL 找到的命名空间范围函数。 C++0x 通过添加“可交换”概念正式认可该技术。
      • @ildjarn @JamesMcNellis 啊。我从来没有真正使用过专门std::swap() 的成语,但我在这里见过有信誉的人这样做。但是,是的,我没有想到明显的:ADL FTW! :)
      • @James:不管你更喜欢哪个,但是,标准确实允许将专业化添加到命名空间std。反对它对于风格指南来说是完全合理的,但说它给出了未定义的行为是完全错误的。
      【解决方案5】:

      这就是说不要在std 命名空间中声明您自己的类型。您可以使用标准库,但您应该通过包含适当的标头来这样做。

      基本上,确保所有声明都在您自己的命名空间中,而不是std

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-11-11
        • 2012-07-19
        • 2011-01-31
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多