As far as I understand (at least for c++14
), a destructor cannot be constexpr
if it is not trivial (implicit generated or =default
). What is the point of declaring constexpr
constructors for structures with non-trivial destructors?
struct X {
int a_;
constexpr X(int a) : a_{a} {}
// constexpr ~X(){}; // Error dtor cannot be marked constexpr
// ~X(){}; // causes error at y declaration: temporary of non-literal type ‘X’
// in a constant expression .
};
template <int N> struct Y {};
int main() {
Y<X{3}.a_> y; // OK only if the destructor is trivial
(void)y;
}
// tested with c++14 g++-5.1.0 and clang++ 3.5.0
For instance std::unique_ptr
has some constructors constexpr
(default and nullptr_t
), even though the destructor is obviously explicitly defined (sure it has no effects if the object is nullptr
, but doesn't that mean that it still has an explicit-defined destructor in order to check if the object is in an empty state, and as I've seen, even an empty destructor doesn't allow an object to be used in a compile-constant expression)
Another example is the proposal for std::variant: it has almost all the constructors constexpr
although the destructor has the signature ~variant()
and it has to call get<T_j> *this).T_j::~T_j() with j being index().
What am I missing?
constexpr
constructors can be used for constant initialization, which, as a form of static initialization, is guaranteed to happen before any dynamic initialization takes place.For example, given a global
std::mutex
:In a conforming implementation (read: not MSVC), constructors of other objects can safely lock and unlock
mutex
, becausestd::mutex
's constructor isconstexpr
.