在标准名称空间中声明名称的不良做法?

ste*_*eve 7 c++ coding-style c++-standard-library

我正在浏览Google C++风格指南,并发现了这个:

"不要在命名空间std中声明任何内容,甚至不要在标准库类的前向声明中声明.在命名空间std中声明实体是未定义的行为,即不可移植.要从标准库声明实体,请​​包含相应的头文件."

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

Jam*_*lis 12

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

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

namespace std {
    void foo(int) { }
}

#include <iostream>

int main() {
    std::cout << "Hello World!" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

为什么?它声明了一个foo在命名空间中命名的函数std.至于为什么会导致问题,请考虑:标准库实现可能有自己的命名函数foo(),可能会被某个组件使用<iostream>.foo然后,您可能会比标准库实现更好地匹配foo.

  • @wilhelmtell:你可以_specialize_`std`模板; 你不能_overload_`std`模板.对于`swap`,正如@ildjarn所说,首选解决方案是使用可以通过ADL找到的命名空间范围函数.C++ 0x通过添加"可交换"概念正式批准该技术. (4认同)
  • @James:不管你喜欢哪个*,标准都特别允许在namespace std中添加特化.针对它提供建议对于样式指南来说是完全合理的,但是说它给出了未定义的行为是完全错误的. (2认同)

Jer*_*fin 12

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

忽略这些例外,但是,他们有正确的总体思路-你的代码通常属于地方其他比空间std.您可以将它放在全局命名空间中,或者您可以定义另一个命名空间,但您应该std单独留下.

你也应该不会尝试在标准库前瞻性声明任何东西.允许标准函数(例如)包含额外参数,只要它们包含默认值,因此可以以标准方式调用它们.如果您尝试自己声明它们,而不是声明现有函数,则最终可能会声明模糊的重载.

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

  • +1"首先,**像Google风格指南**一样**,实际上是错误的." (5认同)

Ree*_*sey 6

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

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


Xeo*_*Xeo 5

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

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

// use std::SomeStandardFunction
Run Code Online (Sandbox Code Playgroud)

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

// myheader.h
#include <SomeHeaderThatContainsSomeStandardFunction>

// use std::SomeStandardFunction
Run Code Online (Sandbox Code Playgroud)