Friday 18 May 2012

One Definition Rule and Unnamed namespaces

It is possible to have multiple (different) definitions of a class with all methods declared as inline, in different translation units. Both compiler and linker do not complain. Compiler sees only a single unit and so only a single definition. Linker treats all definitions of inline class methods equally, picks only one for linking and discards the rest. But different definitions of the same class are introducing undefined behaviour as linker can pick e.g. constructor implementation from one module and method implementation from another. So the client code might potentially call method defined in one module on some object created with constructor defined in another module. Different definitions of the same class within the same program break the One Definition Rule (§3.2, C++11 standard draft N3242=11-0012). (See my Stack Overflow question)

It is possible to define classes with the same name in different translation units in a safe way. Classes are visible in all units because member functions of non-local classes have external linkage by default. It doesn't matter whether methods are declared as inline, static or they are declared without any specifiers. So this is the reason why linker is able to see multiple definitions of the same method, allowing it to (arbitrary) pick the one and discard the rest. We need to suppress this, we need to hide definitions inside translation units. If we had a variable or a function, we could achieve this by declaring it as static and therefore imposing internal linkage on them. But we cannot apply static keyword on classes (user defined types). What we can do is to place class definition in each translation unit inside a unnamed namespace. This way we are limiting class access only to the translation unit this class is defined in and disable breaking of the One Definition Rule.

Links and References:

external vs internal linkage and performance (SO)
Unnamed/anonymous namespaces vs. static functions (SO)
Superiority of unnamed namespace over static? (SO)
Why unnamed namespace is a“ superior” alternative to static? (SO)
static keyword useless in namespace scope? (SO)

No comments: