Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

constexpr global of class type

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 respective inline 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.

Is this all correct? Is there any way to have a constexpr global of class type without wrapping it in an inline function?

like image 678
Potatoswatter Avatar asked Dec 04 '13 07:12

Potatoswatter


People also ask

Is constexpr global?

constexpr function should refer only to constant global variables. constexpr function can call only other constexpr function not simple function.

What does constexpr mean in C++?

The keyword constexpr was introduced in C++11 and improved in C++14. It means constant expression. Like const , it can be applied to variables: A compiler error is raised when any code attempts to modify the value. Unlike const , constexpr can also be applied to functions and class constructors.

When to use #define vs constexpr?

#define directives create macro substitution, while constexpr variables are special type of variables. They literally have nothing in common beside the fact that before constexpr (or even const ) variables were available, macros were sometimes used when currently constexpr variable can be used.

Does constexpr improve performance?

Using constexpr to Improve Security, Performance and Encapsulation in C++ constexpr is a new C++11 keyword that rids you of the need to create macros and hardcoded literals. It also guarantees, under certain conditions, that objects undergo static initialization.


1 Answers

Global constexpr variables can ODR-safely be defined in headers using a bit of macro magic and the proverbial extra level of indirection

#define PP_GLOBAL_CONSTEXPR_VARIABLE(type, var, value)                   \
namespace var##detail {                                                  \
template<class = void>                                                   \
struct wrapper                                                           \
{                                                                        \
     static constexpr type var = value;                                  \
};                                                                       \
template<class T>                                                        \
constexpr type wrapper<T>::var;                                          \
}                                                                        \
namespace {                                                              \
auto const& var = var##detail::wrapper<>::var;                           \
}

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

like image 131
TemplateRex Avatar answered Oct 21 '22 09:10

TemplateRex