7

I was looking through the Google C++ style guide, and came across this:

"Do not declare anything in namespace std, not even forward declarations of standard library classes. Declaring entities in namespace std is undefined behavior, i.e., not portable. To declare entities from the standard library, include the appropriate header file."

Could someone explain what this means and why this is undefined behavior using example code?

fredoverflow
  • 256,549
  • 94
  • 388
  • 662
steve
  • 73
  • 3

5 Answers5

12

Could someone explain what this means and why this is undefined behavior using example code?

The following program yields undefined behavior:

namespace std {
    void foo(int) { }
}

#include <iostream>

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

Why? It declares a function named foo in namespace std. As for why this could cause a problem, consider: the Standard Library implementation might have its own function named foo() and that might be used by some component in <iostream>. Your foo might then be a better match than the Standard Library implementation's foo.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • 1
    Except we do specialize `std::swap<>()`. We're allowed to do that. :p – wilhelmtell Apr 16 '11 at 01:30
  • @wilhelmtell : Even that is very poor form. It's better to define a swap overload in the same namespace as your type and let ADL do the work of finding it. – ildjarn Apr 16 '11 at 01:40
  • 4
    @wilhelmtell: You can _specialize_ `std` templates; you cannot _overload_ `std` templates. For `swap`, the preferred solution, as @ildjarn says, is to use a namespace-scope function that can be found via ADL. C++0x gives formal approval to that technique through the addition of a "Swappable" concept. – James McNellis Apr 16 '11 at 01:41
  • @ildjarn @JamesMcNellis Ah. I never actually use that idiom of specializing `std::swap()` but I've seen reputable people here that do. But yes, I didn't think about the obvious: ADL FTW! :) – wilhelmtell Apr 16 '11 at 02:06
  • 2
    @James: regardless of which you *prefer*, however, the standard does specifically allow adding the specialization to namespace std. Advising against it would be perfectly reasonable for a style guide, but saying it gives undefined behavior is just plain wrong. – Jerry Coffin Apr 16 '11 at 02:34
  • @Jerry: You are right that the style guide's statement that you should not declare _anything_ in `std` is wrong. Though, as you rightly point out in your answer, such a statement is par for the course for the Google C++ "Style" Guide. – James McNellis Apr 16 '11 at 04:02
  • Why is specializing `std::swap` poor form? ADL only kicks in if you call `swap()` unqualified. Wouldn't you want your function to be used even if someone prefixes the call with `std::`? – jalf Apr 16 '11 at 07:32
  • Actually, [this doesn't only ___declare___, but even ___defines___ a function](http://stackoverflow.com/questions/1410563/what-is-the-difference-between-a-definition-and-a-declaration/1410632#1410632) in the `std` namespace. Of course, just a declaration would be undefined behavior, too. And, yes, ___specializing___ templates in the `std` namespace is perfectly fine, while overloading function templates isn't. This you can specialize `std::swap()`, but not overload `std::swap>`. – sbi Apr 16 '11 at 07:36
  • @jalf: It isn't poor form, it's just not very useful if you have a template-heavy codebase since you can't partially specialize function templates. (e.g., given `template X { /* ... */ };`, you can only specialize `std::swap` for particular instantiations of `X` like `X`; you can't specialize it for any arbitrary `X`). – James McNellis Apr 16 '11 at 16:53
  • @jalf You can turn your argument around: why explicitely use `std::swap`, wouldn't you want to match against `swap` implementations in other namespaces too? The appropriate idiom in a template is: `use std::swap; swap(a,b);` – oisyn Jan 17 '18 at 11:34
12

First of all, like much of the Google style guide, it's actually wrong. The standard specifically allows you to define a few specific entities in namespace std (e.g., specializations of existing templates over user defined types).

Ignoring those exceptions, however, they do have the right general idea -- your code normally belongs somewhere other than namespace std. You can put it in the global namespace, or you can define another namespace, but you should leave std alone.

You also should not try to forward-declare anything in the standard library. Standard functions are allowed (for example) to include extra parameters, as long as they include default values, so they can be invoked in the standard way. If you try to declare them yourself, instead of declaring the existing function, you could end up declaring an ambiguous overload instead.

Bottom line: yes, use the standard library. When you do use it, get the declarations by including the standard header(s), not by trying to write your own.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • 1
    +1 for beating me to it: "it's actually wrong. ... specializations of existing templates ...". It's a common and acceptable practice to specialize `std::swap<>()`. – wilhelmtell Apr 16 '11 at 01:28
  • 5
    +1 for "First of all, **like much of the Google style guide**, it's actually wrong." – ildjarn Apr 16 '11 at 02:29
6

This is saying not to declare your own types in the std namespace. You can use the standard library, but you should do so by including the appropriate header.

Basically, make sure all of your declarations are in your own namespace, not std.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
5

They're saying that you shouldn't forward declare stuff from the standard library like this:

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

// use std::SomeStandardFunction

Instead, you should just include the header directly:

// myheader.h
#include <SomeHeaderThatContainsSomeStandardFunction>

// use std::SomeStandardFunction
Xeo
  • 129,499
  • 52
  • 291
  • 397
  • Missing whitespace: template > vector; (-: – snoofkin Apr 16 '11 at 01:41
  • @soul: More glaring problem was a missing `;` after `allocator`, and that `allocator` needs to be fully defined before being used as a template parameter, so I changed the example. :) – Xeo Apr 16 '11 at 01:49
2

This isn't saying "Do not use the standard library".

To use something, and to declare something, are two different things. It's saying don't declare anything as in don't do something like "class ostream;". I guess people used to have to declare it like that in order to use it, but now, since things are declared in namespace std, you simply include the header file.

Check this out.

Community
  • 1
  • 1
Andrew Rasmussen
  • 14,912
  • 10
  • 45
  • 81