Подтвердить что ты не робот

Зачем объявлять конструкторы constrexpr для классов с нетривиальными деструкторами (например, unique_ptr, std:: variant)

Насколько я понимаю (по крайней мере, для c++14), деструктор не может быть constexpr, если он не является тривиальным (неявным сгенерированным или =default). В чем смысл объявления конструкторов constexpr для структур с нетривиальными деструкторами?

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

Например, std::unique_ptr имеет некоторые конструкторы constexpr (по умолчанию и nullptr_t), хотя деструктор явно явно определен (уверен, что он не имеет эффектов если объект nullptr, но это не значит, что он все еще имеет явно определенный деструктор, чтобы проверить, находится ли объект в пустом состоянии, и, как я видел, даже пустой деструктор не разрешить использование объекта в выражении с компиляцией)

Другим примером является предложение std:: variant: у него почти все конструкторы constexpr, хотя деструктор имеет подпись ~variant(), и он должен call get<T_j> *this).T_j::~T_j() with j being index().

Что мне не хватает?

4b9b3361

Ответ 1

Конструкторы

constexpr могут использоваться для постоянной инициализации, которая, как форма статической инициализации, гарантируется, прежде чем произойдет любая динамическая инициализация.

Например, с учетом глобального std::mutex:

std::mutex mutex;

В соответствующей реализации (read: not MSVC) конструкторы других объектов могут безопасно блокировать и разблокировать mutex, потому что конструктор std::mutex constexpr.