在标准命名空间中声明名称是否是不良实践?

7
我在查看Google C++风格指南时,发现了这个内容:
"不要在命名空间std中声明任何东西,甚至不是标准库类的前向声明。在命名空间std中声明实体是未定义的行为,即不可移植的。要声明来自标准库的实体,请包含适当的头文件。"
有人能解释一下这是什么意思以及为什么这是未定义的行为并提供示例代码吗?
5个回答

12

能有人解释一下这段代码的含义,以及为什么它是未定义行为吗?附上示例代码。

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

namespace std {
    void foo(int) { }
}

#include <iostream>

int main() {
    std::cout << "Hello World!" << std::endl;
}

为什么?它在命名空间std中声明了一个名为foo的函数。至于为什么这可能会引起问题,可以考虑以下情况:标准库实现可能有自己的名为foo() 的函数,并且某些组件在<iostream>中可能使用它。您的foo可能比标准库实现的foo更匹配。


1
除了我们专门处理 std::swap<>()。我们被允许这样做。:p - wilhelmtell
@wilhelmtell:即使如此也是非常不好的形式。最好在与您的类型相同的命名空间中定义一个交换重载,并让ADL完成查找工作。 - ildjarn
4
您可以对std模板进行特化;但不能对std模板进行重载。对于swap,正如@ildjarn所说,首选解决方案是使用命名空间作用域函数,可以通过ADL找到该函数。C++0x通过添加“可交换”概念,对该技术进行了正式批准。 - James McNellis
2
@James:无论你喜欢哪个,标准确实允许将专业化添加到命名空间std中。对于样式指南建议不这样做是完全合理的,但说它会导致未定义的行为就是完全错误的。 - Jerry Coffin
@jalf 你可以反过来考虑你的论点:为什么要明确使用 std::swap,难道你不想匹配其他命名空间中的 swap 实现吗?在模板中适当的习惯用法是:use std::swap; swap(a,b); - oisyn
显示剩余5条评论

12

首先,和 Google 的大部分风格指南一样,这个建议是错误的。标准明确允许你在 std 命名空间中定义几个特定的实体(例如,对用户定义类型进行现有模板的特化)。

不过,忽略这些例外,他们确实有正确的基本想法——你的代码通常应该存在 其他 命名空间中。你可以将它放在全局命名空间中,或者定义另一个命名空间,但是你应该不要改动 std

你也 不应该 尝试前置声明任何标准库中的内容。标准函数允许(例如)包括额外参数,只要它们包含默认值,就可以按标准方式调用。如果你尝试自己声明它们,而不是声明已有的函数,则可能会声明出一个歧义的重载。

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


1
+1 为了比我先说出来:“实际上是错误的……现有模板的特化……”。特化 std::swap<>() 是一种常见且可接受的做法。 - wilhelmtell
5
+1,首先,就像 Google 风格指南的很多内容一样,它实际上是错误的。 - ildjarn

6

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

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


5
他们说你不应该像这样 前向声明 标准库的内容:
// myheader.h
namespace std{
template<class T>
void SomeStandardFunction();
}

// use std::SomeStandardFunction

相反,您应该直接包含标题:
// myheader.h
#include <SomeHeaderThatContainsSomeStandardFunction>

// use std::SomeStandardFunction

缺少空格:template<class T,class Alloc = allocator<T> > vector; (-: - snoofkin
@soul:更加明显的问题是在allocator后缺少了 ;,而且作为模板参数使用前需要完整定义allocator,因此我已经修改了示例。 :) - Xeo

2

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

使用和声明是两回事。它的意思是不要像这样声明任何东西,比如"类 ostream"。我想过去人们必须这样声明才能使用它,但现在,由于在命名空间 std 中声明了这些内容,你只需包含头文件即可。

请查看这个


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接