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?
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.)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With