I have something similar to the following
class Base {
public:
explicit Base(int* i) noexcept { type = new int; *type = *i; };
constexpr Base(std::nu
The type of a constant expression must be a literal type. In fact, the entire purpose of the "literal type" taxon is to "be the thing that can be a constant expression". See [expr.const]:
A conditional-expression
e
is a core constant expression unless the evaluation ofe
, following the rules of the abstract machine (1.9), would evaluate one of the following expressions:...
— an invocation of a function other than a constexpr constructor for a literal class, a constexpr function,
...
Therefore, a constexpr
constructor only allows you to produce constant expressions on literal classes, and otherwise, as your compiler is telling you, it would "never produce a constant expression".
A literal class is constrained by [basic.types] in this way:
A type is a literal type if it is:
...
— a class type (Clause 9) that has all of the following properties:
- it has a trivial destructor,
- it is an aggregate type (8.5.1) or has at least one
constexpr
constructor or constructor template that is not a copy or move constructor, and- all of its non-static data members and base classes are of non-volatile literal types.
However, as of C++14 (particularly, as of N3652), constexpr
constructors have another, unrelated use: They permit static initialization (in the sense of [basic.start.init]):
A constant initializer for an object
o
is an expression that is a constant expression, except that it may also invokeconstexpr
constructors foro
and its subobjects even if those objects are of non-literal class types [Note: such a class may have a non-trivial destructor — end note].
So to recap: As of C++14, constexpr
has two uses:
The C++11 interpretation: a "constant expression" is an expression that is identical to its value (i.e. its evaluation has no side effects); constexpr
variables are just placeholders for their value and not intended to be used for their object identity, and it is generally expected that constant expressions can be freely replaced with their (compile-time knowable) value.
The C++14 constexpr
functions, including constructors: These functions, including constructors, may be called in the static initialization phase to constant-initialize variables with static storage duration. If the variables are objects, they still retain their object identity and may need dynamic destruction, but their initialization happens before any dynamic initialization and is not subject to ordering.