c++ - constexpr for null-initialized constructor in a derived class -
i have similar following
class base { public: explicit base(int* i) noexcept { type = new int; *type = *i; }; constexpr base(std::nullptr_t) : type(nullptr) { }; ~base() { cout << "destroying!" << endl; delete type; }; protected: int* type; }; class derived : public base { public: explicit derived(int* i) noexcept : base(i) { }; //constexpr derived(std::nullptr_t) : type(nullptr) { }; //constexpr derived(std::nullptr_t) : base(nullptr) { }; ~derived() { }; };
i achieve constexpr
null constructor derived class, compiler complains lot 2 options , similar tests have done.
of course code more complex, have opaque handler , destructor should behave in more complex way. resource free-ing same (no need multiple destructors, base
one).
i don't know how achieve this, maybe going through wrong path? ideas? expect able like:
derived a(nullptr); derived b(handler1); base c (nullptr); base d (handler2);
and, in cleanup, both handler1
, handler2
managed in way.
edit:
clang (version 3.4) complains:
error: constexpr constructor never produces constant expression [-winvalid-constexpr]
and gcc (version 4.8 [edit: multiple versions, haven't checked all]) doesn't complain when using
constexpr derived(std::nullptr_t) : base(nullptr) { };
in fact, gcc
seems wanted achieve, not understand constexpr
enough know compiler doing right , how can amend problem.
the type of constant expression must literal type. in fact, entire purpose of "literal type" taxon "be thing can constant expression". see [expr.const]:
a conditional-expression
e
core constant expression unless evaluation ofe
, following rules of abstract machine (1.9), evaluate 1 of following expressions:...
— invocation of function other a constexpr constructor literal class, constexpr function,
...
therefore, constexpr
constructor allows produce constant expressions on literal classes, , otherwise, compiler telling you, "never produce constant expression".
a literal class constrained [basic.types] in way:
a type literal type if is:
...
— class type (clause 9) has of following properties:
- it has trivial destructor,
- it aggregate type (8.5.1) or has @ least 1
constexpr
constructor or constructor template not copy or move constructor, and- all of non-static data members , base classes of non-volatile literal types.
however, of c++14 (particularly, of n3652), constexpr
constructors have another, unrelated use: permit static initialization (in sense of [basic.start.init]):
a constant initializer object
o
expression constant expression, except may invokeconstexpr
constructorso
, subobjects if objects of non-literal class types [note: such class may have non-trivial destructor — end note].
so recap: of c++14, constexpr
has 2 uses:
the c++11 interpretation: "constant expression" expression identical value (i.e. evaluation has no side effects);
constexpr
variables placeholders value , not intended used object identity, , expected constant expressions can freely replaced (compile-time knowable) value.the c++14
constexpr
functions, including constructors: these functions, including constructors, may called in static initialization phase constant-initialize variables static storage duration. if variables objects, still retain object identity , may need dynamic destruction, initialization happens before dynamic initialization , not subject ordering.
Comments
Post a Comment