The problem is make_magic . [Basic.def.odr] / p6:
There may be more than one definition ... an embedded function with an external connection (7.1.2) ... in a program, provided that each definition appears in a different translation unit and provides definitions that satisfy the following requirements. Given such an object called D , defined in more than one translation unit, then
- each definition of
D must consist of the same sequence of tokens; and - in each definition of
D , the corresponding names scanned in accordance with 3.4 refer to the entity defined in definition D , or must refer to the same object after resolving overload (13.3) and after matching partial type specialization (14.8.3), except that the name can refer to a non-volatile const object with internal or no binding, if the object has the same literal type in all of D definitions, and the object is initialized with constant expression (5.20), and the object is not used odr, and the object has the same value in all definitions of D ; and - [...]
Since piecewise_construct and magic_number are internally linked when the built-in make_magic function make_magic defined in several translation units, the names piecewise_construct and magic_number refer to different objects - TU 1 make_magic will refer to TU 1 piecewise_construct and magic_number , and TU 2 make_magic will refer to TU 2 piecewise_construct magic_number . Since the created tuple constructor takes arguments by reference, the lvalue-to-rval conversion is not performed, the objects are used by odr, and the exception in the second pool is not applied, and you have an ODR violation.
(By the way, std::tuple does not have a piecewise_construct constructor, and in any case, such a constructor will presumably take tuples as arguments, not a simple int , but one that is orthogonal to the point that it is trying to make.)
source share