One-Definition-Rule defines rules for two scopes, i.e. translation unit scope and program scope.
The following rule with translation unit scope states that the same translation unit must not comprise two different definitions of the same function:
Only one definition of any variable, function, class type, enumeration
type, or template is allowed in any one translation unit (some of
these may have multiple declarations, but only one definition is
allowed).
So, if you have two different .cpp-files, than you have two different translation units, and each of them may have their own definition of hello()
; ODR is not violated in the scope of a translation unit.
The following rule with program scope defines that an odr-used function must be defined exactly once in the program:
One and only one definition of every non-inline function or variable
that is odr-used (see below) is required to appear in the entire
program (including any standard and user-defined libraries). The
compiler is not required to diagnose this violation, but the behavior
of the program that violates it is undefined.
The definition of odr-used informally states that for every function that is called or which's address is taken must be defined in the program:
Informally, an object is odr-used if its address is taken, or a
reference is bound to it, and a function is odr-used if a function
call to it is made or its address is taken. If an object or a
function is odr-used, its definition must exist somewhere in the
program; a violation of that is a link-time error.
So, if more than one .cpp-file exposes an implementation of hello()
, and if this function is called or referenced, then ODR from program scope is clearly violated.
If the respective function is not odr-used (i.e. called or referenced), ODR should - to my understanding - not be violated;
If a compiler complains about duplicate symbols, than this is because the program violates linkage rules (please confer also SO answer concerning "If I don't odr-use a variable"). C++11 §3.5[basic.link]/9 states:
Two names that are the same and that are declared in different scopes
shall denote the same variable, function, type, enumerator, template
or namespace if
- both names have external linkage or else both names have internal linkage and are declared in the same translation unit; and ...
To avoid this, make sure that at most one implementation of hello()
is exposed, and make all others static
or use an unnamed namespace.
In the C programming language, static
is used with global variables and functions to set their scope to the containing file, i.e. it does not expose this implementation and name clashes with other binaries are avoided.
So a reasonable suggestion would be: Make function definitions, that are solely used within a translation unit, visible only to this translation unit; and define functions that are exposed within a namespace or class in order to avoid unintended or unforeseeable name clashes / duplicate symbol problems in the linker.