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

Почему деструктор не может быть отмечен как constexpr?

В С++ вы можете объявить много вещей как constexpr: переменные, функции (включая функции-члены и операторы), конструкторы, а так как С++ 1z, также if statements и лямбда-выражения. Однако объявление destructor constexpr приводит к ошибке:

struct X {
    constexpr ~X() = default; // error: a destructor cannot be 'constexpr'
};

Мои вопросы:

  • Почему деструктор не может быть помечен constexpr?
  • Если я не предоставляю деструктор, это неявно сгенерированный деструктор constexpr?
  • Если я объявляю деструктор по умолчанию (~X() = default;), автоматически ли он constexpr?
4b9b3361

Ответ 1

В соответствии с draft basic.types # 10, возможно, с классом класса cv, который обладает всеми следующими свойствами:

Возможно, класс класса с квалификацией, который имеет все следующие свойства:

(10.5.1) - он имеет тривиальный деструктор,

(10.5.2) - это либо тип замыкания, совокупный тип, либо имеет как минимум один конструктор конструктора или шаблон конструктора (возможно унаследованный от базового класса), который не является конструктором копирования или перемещения,

(10.5.3) - если это объединение, по крайней мере одна из его нестатических данных члены имеют нелетучий тип литерала

(10.5.4) - если это не объединение, все его нестатические элементы данных и базовые классы нелетучие литералы.

Ques 1: Почему деструктор не может быть помечен как constexpr?

Поскольку только тривиальные деструкторы квалифицируются для constexpr Ниже приведен соответствующий раздел draft

Деструктор тривиален, если он не предоставляется пользователем, и если:

(5.4) - деструктор не является виртуальным,

(5.5) - все прямые базовые классы его класса тривиальны деструкторы и

(5.6) - для всех нестатических членов данных своего класса, которые типа (или его массива), каждый такой класс имеет тривиальный деструктор.

В противном случае деструктор не является тривиальным.

Ques 2: Если я не предоставляю деструктор, это неявно созданный деструктор constexpr?

Да, потому что неявно сгенерированный деструктор является тривиальным типом, поэтому он доступен для constexpr

Ques 3: Если я объявляю деструктор по умолчанию (~ X() = default;), то он автоматически constexpr?

В действительности, этот деструктор объявляется пользователем и неявно сгенерирован и, следовательно, имеет право на constexpr.


Я не могу найти какую-либо прямую ссылку, для которой только тривиальный destructors имеет значение для constexpr, но если деструктор не является тривиальным, то это точно, что тип класса не является cv-qualified.. Таким образом, это неявный поскольку вы не можете определить класс destructor для cv-qualified.

Ответ 2

Почему деструктор не может быть помечен как constexpr?

Стандарт С++ 11 специфичен для использования constexpr для конструировщиков и нестатической функции-члена. Он не говорит ничего конкретного о деструкторе. Можно предположить, что деструкторы должны рассматриваться как нестатические функции-члены.

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

Если я не предоставляю деструктор, это неявно сгенерированный деструктор constexpr.

Так как использование

constexpr ~X() = default;

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

Если я объявляю деструктор по умолчанию (~X() = default;), автоматически ли он constexpr

Думаю, что нет. Еще раз, я не могу найти ничего в стандарте, чтобы оправдать свое утверждение. Я предполагаю.


FWIW, g++ компилирует и строит следующую программу просто отлично.

struct X {
   constexpr X(int i) : i_(i) {}
   ~X() = default;
   int i_;
};

int main()
{
   const X x(10);
}

Ответ 3

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

Объект не может быть constexpr, если его деструктор нетривиален. По умолчанию, если тривиально, будет считаться constexpr

Live

От [class.dtor]

Каждый спецификатор decl-specifier-seq объявления деструктора (если он есть) должен быть friend, inline или virtual.

Отсутствует, constexpr. Таким образом, вы можете просто взять это как: поскольку стандарт говорит, что TM

Ответ 4

Ссылка say's:

constexpr destructors

В большинстве случаев для создания объекта типа T в константе выражение, разрушение T должно быть тривиальным. Однако нетривиальные деструкторы являются важным компонентом современного С++, отчасти из-за широко распространенное использование идиомы RAII, которое также применимо в constexpr. Нетривиальные деструкторы могут поддерживаться в постоянные выражения следующим образом:

  • Разрешить деструкторы отмечать как constexpr
  • Сделать декомпрессированные по умолчанию дескрипторы constexpr, если они только вызывают конструкторы constexpr
  • Для переменных constexpr требуется, чтобы оценка деструктора была константным выражением (за исключением того, что уничтожаемый объект может быть изменен в собственном деструкторе

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