Search code examples
c++language-lawyerlinkageone-definition-ruleinline-functions

ODR violation due to anonymous namespace in header


From reading the standard I was unable to figure out if the following code violates ODR:

// a.h
#ifndef A_HEADER_FILE
#define A_HEADER_FILE

namespace {
int v;
}

inline int get_v() { return v; }

#endif // A_HEADER_FILE

// a.cpp
#include "a.h"

void f() {
  int i = get_v();
  // ...
}

// b.cpp
#include "a.h"

void g() {
  int i = get_v();
  // ...
}

(Source: https://wiki.sei.cmu.edu/confluence/display/cplusplus/DCL59-CPP.+Do+not+define+an+unnamed+namespace+in+a+header+file)

Supposedly, get_v() references different variables in each translation unit so it violates ODR.

This answer: Inline functions and external linkage says that inline relaxes ODR so I am not sure why this is still an error?

Can someone link me to where in the standard it is specified if this is an ODR violation or not?


Solution

  • An inline function is allowed to have multiple definitions (C++17 [basic.def.odr]/6). This is the sense in which inline functions can be used to prevent ODR violations. However, the multiple definitions of the inline function must be consistent with each other. To be specific, [basic.def.odr]/6.2 says:

    in each definition of D, corresponding names, looked up according to 6.4, shall refer to an entity defined within the definition of D, or shall refer to the same entity [...] [some exceptions]

    The multiple definitions of get_v refer to the variable v, but v is not defined within get_v. Therefore, it is required that each definition of get_v reference the same variable v. This is not the case, since each translation unit has a different v. Therefore, the ODR is violated.