Почему деструктор не может быть отмечен как constexpr?
В С++ вы можете объявить много вещей как constexpr
: переменные, функции (включая функции-члены и операторы), конструкторы, а так как С++ 1z, также if
statements и лямбда-выражения. Однако объявление destructor constexpr
приводит к ошибке:
struct X {
constexpr ~X() = default; // error: a destructor cannot be 'constexpr'
};
Мои вопросы:
- Почему деструктор не может быть помечен
constexpr
?
- Если я не предоставляю деструктор, это неявно сгенерированный деструктор
constexpr
?
- Если я объявляю деструктор по умолчанию (
~X() = default;
), автоматически ли он constexpr
?
Ответы
Ответ 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 требуется, чтобы оценка деструктора была константным выражением (за исключением того, что уничтожаемый объект может быть изменен в собственном деструкторе
Однако для такой функции не известны убедительные примеры использования и существует нетривиальная стоимость реализации, обеспечивающая деструкторы запускаются в нужное время.