Look at this code:
struct NonConstexpr {
NonConstexpr() { }
};
template <typename T>
struct Bar {
NonConstexpr nonConstexpr;
constexpr Bar() { }
};
struct Foo {
Bar<void> bar;
constexpr Foo() { }
};
Foo
has a member, Foo::bar::nonConstexpr
, which has a non-constexpr constructor. So, my expectation is that this should not compile. But it compiles with gcc, clang and msvc. Is this a compiler bug, or some rule allows this code to compile?
If I add a NonConstexpr
member into Foo
directly, the code doesn't compile anymore.
(I got this problem, because I've expected static initialization for a global Foo
object, but it got dynamically initialized, and it caused a problem, because of "static initialization order fiasco")
A constexpr function must accept and return only literal types. A constexpr function can be recursive. It can't be virtual. A constructor can't be defined as constexpr when the enclosing class has any virtual base classes.
constexpr stands for constant expression and is used to specify that a variable or function can be used in a constant expression, an expression that can be evaluated at compile time. The key point of constexpr is that it can be executed at compile time.
A constexpr function that is eligible to be evaluated at compile-time will only be evaluated at compile-time if the return value is used where a constant expression is required. Otherwise, compile-time evaluation is not guaranteed.
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.
Is this a compiler bug, or some rule allows this code to compile?
The rule that allows this to compile is:
10.1.5 The constexpr specifier [dcl.constexpr]
...
6. If the instantiated template specialization of aconstexpr
function template or member function of a class template would fail to satisfy the requirements for aconstexpr
function orconstexpr
constructor, that specialization is still aconstexpr
function orconstexpr
constructor, even though a call to such a function cannot appear in a constant expression. If no specialization of the template would satisfy the requirements for aconstexpr
function orconstexpr
constructor when considered as a non-template function or constructor, the template is ill-formed, no diagnostic required.
The above quote is taken from CPP standard draft N4713.
From the quote it may not be clear how Bar<void>
's constructor can appear in Foo
's constructor as Foo
's constructor is constexpr
. But as noted in the comments, constexpr
is not the same as constant expression. Foo
's constructor is is not an expression, much less a constant expression.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With