My understanding is that constexpr
globals of class type are all but unusable because
Such an object must be defined in every TU, because
constexpr
does not permit forward declaration of an object.Default linkage as
static
would cause naming the object (ODR-use or not) in an inline function to violate the ODR, because the respectiveinline
definitions would have different meaning.Declaration as
extern constexpr
with one definition per TU would violate the ODR rule if the object is ODR-used, which occurs when a reference to it is taken.- A reference is taken for an implicit
this
parameter, even if it's unused by a member function. - Obviously happens if you try to pass the object by reference.
- Also happens if you try to pass the object by value, which implicitly uses a copy or move constructor, which by definition passes by reference.
- GCC and Clang both complain of ODR violations (multiple definitions) if an object is declared
extern constexpr
even if not ODR-used.
- A reference is taken for an implicit
Is this all correct? Is there any way to have a constexpr
global of class type without wrapping it in an inline
function?
Global constexpr variables can ODR-safely be defined in headers using a bit of macro magic and the proverbial extra level of indirection
The macro provides a reference inside an unnamed namespace to an object instance in an implementation class template.
Each object in an unnamed namespace inside a header generates a unique instance in every translation unit that includes its header. Furthermore, to prevent ODR violations, it is important that the objects in e.g. multiple instantiations of a function template are the same.
However, for references it doesn't matter that they have a different identity; as long as they refer to the same object instance in an implementation class template.
You can wrap this macro in a header and safely include it in many TUs without a problem.
See the following discussion on the Boost mailinglist for more details: http://lists.boost.org/Archives/boost/2007/06/123380.php