Beware. The ODR only concerns definitions that will be included in the resulting program. That means that is does not concern symbols that could be present in libraries, because a (normal) linker does not load the whole libraries, but only the parts that are required to resolve symbols. For example in this code:
#include <cmath>
double log(double) {return 1.0;}
int main()
{
log(1.0);
}
There is no violation of the ODR:
- either the log symbol from the C standard library was only included in the
std
namespace and there is no collision at all
- or it is also included in global namespace
In latter case, the declaration double log(double)
does not conflict with the one from cmath because it is the same. And as the symbol log
is already defined, its definition from the standard library will not be included in the program. As such, only one definition for the log
function exists in the program, that one: double log(double) {return 1.0;}
.
Things would be different if you extracted the object module containing log
from the math library and explicitely link it in your program. Because object modules are always included in the resulting program whereas object modules in libraries are only conditionaly included if they resolve undefined symbols.
References from standard:
Draft n3337 for C++11 or n4296 for C++14 (or n4618 for last revision) are explicit in paragraph 2.2 Phases of translation [lex.phases]:
§9. All external entity references are resolved. Library components are linked to satisfy external references
to entities not defined in the current translation. All such translator output is collected into a program
image which contains information needed for execution in its execution environment.
As shown code uses only one translation unit and as log
is already defined in it, the definition from the library will not be used.