Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How would use of unnamed namespaces in headers cause ODR-violations?

In the Google C++ Style Guide, the Namespaces section states that "Use of unnamed namespaces in header files can easily cause violations of the C++ One Definition Rule (ODR)."

I understand why not using unnamed namespaces in an implementation file can cause ODR-violations, but not how use in a header can do so. How can this cause a violation?

like image 876
boycy Avatar asked May 14 '14 10:05

boycy


2 Answers

The reason is that if you actually use anything in the anonymous namespace, you risk undefined behavior. For example:

namespace {
double const pi = 3.14159;
}

inline double twoPiR( double r ) { return 2.0 * pi * r; }

The rule for inline functions (and classes, and templates, and anything else which must be defined in multiple translation units) is that the tokens must be identical (normally the case, unless you hit some macro), and that all symbols must bind identically. In this case, each translation unit has a separate instance of pi, so the pi in twoPiR binds to a different entity in each translation unit. (There are a few exceptions, but they all involve integral expressions.)

Of course, even without the anonymous namespace, this would be undefined behavior here (since const means internal linkage by default), but the basic principle holds. Any use in a header of anything in an unnamed namespace (or any const object defined in the header) is likely to cause undefined behavior. Whether it is a real problem or not depends, but certainly anything which really involves the address of pi, above, is going to cause problems. (I say "really" here, because there are many cases where the address or a reference is formally used, but in practice, the inline expansion will result in the value actually being used. And of course, the token 3.14159 is 3.14159 regardless of where it appears.)

like image 125
James Kanze Avatar answered Sep 19 '22 00:09

James Kanze


In test.h

namespace {
  int x;
}

namespace{
  int x;
}

Including that header file in any source file will case ODR violation, since x is defined twice. This occurs because an unnamed namespace is given a unique identifer by the compiler, and all occurrences of an unnamed namespace in a translation unit are given the same identifier. To paraphrase: every TU has at most one unnamed namespace.

like image 25
Rakib Avatar answered Sep 18 '22 00:09

Rakib