【发布时间】:2011-08-06 17:29:17
【问题描述】:
我正在浏览Google C++ style guide,发现了这个:
“不要在命名空间std中声明任何东西,甚至不要前向声明标准库类。在命名空间std中声明实体是未定义的行为,即不可移植。要从标准库中声明实体,请包含适当的头文件。”
有人可以使用示例代码解释这意味着什么以及为什么这是未定义的行为吗?
【问题讨论】:
标签: c++ coding-style c++-standard-library
我正在浏览Google C++ style guide,发现了这个:
“不要在命名空间std中声明任何东西,甚至不要前向声明标准库类。在命名空间std中声明实体是未定义的行为,即不可移植。要从标准库中声明实体,请包含适当的头文件。”
有人可以使用示例代码解释这意味着什么以及为什么这是未定义的行为吗?
【问题讨论】:
标签: c++ coding-style c++-standard-library
他们说你不应该转发像这样声明标准库中的东西:
// myheader.h
namespace std{
template<class T>
void SomeStandardFunction();
}
// use std::SomeStandardFunction
相反,您应该直接包含标题:
// myheader.h
#include <SomeHeaderThatContainsSomeStandardFunction>
// use std::SomeStandardFunction
【讨论】:
allocator 之后缺少;,并且allocator 在用作模板参数之前需要完全定义,所以我更改了示例。 :)
首先,就像许多 Google 风格指南一样,它实际上是错误的。该标准特别允许您在命名空间 std 中定义一些特定实体(例如,现有模板对用户定义类型的特化)。
然而,忽略这些异常,它们确实有正确的总体思路——您的代码通常属于命名空间 std 之外的某个位置其他。你可以把它放在全局命名空间中,也可以定义另一个命名空间,但你应该不理会std。
您还应该不尝试在标准库中前向声明任何内容。允许(例如)标准函数包含额外参数,只要它们包含默认值,因此可以以标准方式调用它们。如果您尝试自己声明它们,而不是声明现有函数,您最终可能会声明一个模棱两可的重载。
底线:是的,使用标准库。当您使用它时,请通过包含标准标头而不是尝试编写自己的标头来获取声明。
【讨论】:
std::swap<>() 是一种常见且可接受的做法。
这并不是说“不要使用标准库”。
使用某物和声明某物是两件不同的事情。它是说不要声明任何东西,就像不要做“class ostream;”之类的事情。我想人们过去必须这样声明才能使用它,但现在,由于东西是在命名空间 std 中声明的,你只需包含头文件。
签出this。
【讨论】:
有人可以使用示例代码解释这意味着什么以及为什么这是未定义的行为吗?
以下程序产生未定义的行为:
namespace std {
void foo(int) { }
}
#include <iostream>
int main() {
std::cout << "Hello World!" << std::endl;
}
为什么?它在命名空间std 中声明了一个名为foo 的函数。至于为什么这会导致问题,请考虑:标准库实现可能有自己的名为foo() 的函数,并且可能被<iostream> 中的某些组件使用。你的foo 可能比标准库实现的foo 更匹配。
【讨论】:
std::swap<>()。我们被允许这样做。 :p
std模板;你不能overload std 模板。对于swap,正如@ildjarn 所说,首选的解决方案是使用可以通过ADL 找到的命名空间范围函数。 C++0x 通过添加“可交换”概念正式认可该技术。
std::swap() 的成语,但我在这里见过有信誉的人这样做。但是,是的,我没有想到明显的:ADL FTW! :)
这就是说不要在std 命名空间中声明您自己的类型。您可以使用标准库,但您应该通过包含适当的标头来这样做。
基本上,确保所有声明都在您自己的命名空间中,而不是std。
【讨论】: