C++では、多くのことを constexpr
:変数、関数(メンバー関数と演算子を含む)、コンストラクターとして宣言できます。C++ 1z以降は if
ステートメント および ラムダ式 。ただし、 destructorconstexpr
を宣言するとエラーが発生します。
_struct X {
constexpr ~X() = default; // error: a destructor cannot be 'constexpr'
};
_
私の質問:
constexpr
を付けることができないのはなぜですか?constexpr
ですか?~X() = default;
)を宣言すると、自動的にconstexpr
になりますか?draft basic.types#1 によると、以下のすべてのプロパティを持つcv修飾されたクラスタイプである可能性があります。
次のすべてのプロパティを持つcv修飾されている可能性のあるクラス型。
(10.5.1)-簡単なデストラクタがあります。
(10.5.2)-クロージャー型、集約型のいずれかであるか、またはコピーまたは移動コンストラクターではない、少なくとも1つのconstexprコンストラクターまたはコンストラクターテンプレート(基本クラスから継承されている可能性があります)があります。
(10.5.3)-ユニオンの場合、その非静的データメンバーの少なくとも1つは非揮発性リテラルタイプ
(10.5.4)-ユニオンではない場合、その非静的データメンバーと基本クラスはすべて非揮発性リテラル型です。
質問1:デストラクターをconstexprとしてマークできないのはなぜですか?
些細なデストラクタのみがconstexprの資格があるため、以下は draft の関連セクションです
デストラクタは、ユーザー指定ではなく、次の場合に簡単です。
(5.4)—デストラクタは仮想ではありません。
(5.5)—そのクラスのすべての直接基本クラスには、簡単なデストラクタがあります。
(5.6)—クラス型(またはその配列)であるそのクラスのすべての非静的データメンバーについて、そのような各クラスには自明なデストラクタがあります。
それ以外の場合、デストラクタは重要です。
質問2:デストラクタを提供しない場合、暗黙的に生成されたデストラクタはconstexprですか?
はい、暗黙的に生成されたデストラクタは自明な型なので、constexprに適格です。
質問3:デフォルトのデストラクタを宣言した場合(〜X()= default;)、それは自動的にconstexprですか?
実際、このデストラクタはユーザーが宣言し、暗黙的に生成されるため、constexprに対応しています。
些細なdestructors
だけがconstexpr
に適格であるという直接参照を見つけることができませんが、デストラクタが自明でない場合は、クラス型がcv-qualified.
ではないことは確かですしたがって、cv-qualified
クラスに対してdestructor
を定義できないため、これは暗黙的なものです。
C++ 20以降、ユーザー定義のデストラクタは、特定の条件下でconstexprになることもあります。
Constexpr関数の定義は、次の要件を満たす必要があります。
- その戻り値の型(存在する場合)はリテラル型です。
- それぞれのパラメーター型はリテラル型でなければなりません。
- コルーチン([dcl.fct.def.coroutine])であってはなりません。
- 関数がコンストラクタまたはデストラクタの場合、そのクラスには仮想基本クラスがあってはなりません。
- その関数本体は([stmt.pre])を囲んではなりません。
- gotoステートメント、
- 識別子ラベル([stmt.label])、
- 非リテラル型の変数の定義、または静的またはスレッドのストレージ期間。
あなたが探しているものが制限の背後にある理由である場合は、 この論文 を見てください。これは、制限が人工的なものであることを明確に示しています-constexprコンテキストでの動作を妨げるデストラクタの固有のプロパティはなく、実際コンパイラの実装者は、constexprコンテキストでそれらをサポートすることは簡単に実装できることに同意します。
C++標準委員会は当初、C++ 11に制限を設けていたと思います。なぜなら、彼らはその時点でデストラクタを扱いたくなく、完全に除外する方が簡単だったからです。
デストラクタをconstexprとしてマークできないのはなぜですか?
C++ 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);
}
_
デストラクタをconstexpr
にすることはできません。これは、constexpr
関数には副作用がなく、デストラクタは当然のことながら副作用によってのみ役立つためです。つまり、constexpr
のデストラクタを使用しても意味がありません。
デストラクタが自明でない場合、オブジェクトをconstexpr
にすることはできません。デフォルトのものは、取るに足らない場合、constexpr
と見なされます
From [[class.dtor]
デストラクタ宣言のdecl-specifier-seqの各decl-specifier(存在する場合)は、
friend
、inline
、またはvirtual
でなければなりません。
そこにありません、constexpr
。だからあなたはそれを次のように取ることができます:標準がそう言っているのでTM
参考 言う:
constexprデストラクタ
ほとんどの場合、定数式でT型のオブジェクトを作成するには、Tの破棄は簡単でなければなりません。ただし、重要なデストラクタは最近のC++の重要なコンポーネントです。これは、RAIIイディオムが広く使用されているためであり、これはconstexpr評価にも適用できます。次のように、自明ではないデストラクタを定数式でサポートできます。
- デストラクタをconstexprとしてマークできるようにする
- Constexprデストラクタのみを呼び出す場合、デフォルトのデストラクタをconstexprにする
- Constexpr変数の場合、デストラクタの評価が定数式であることを要求します(破棄されるオブジェクトが独自のデストラクタで変更される可能性がある場合を除く)
ただし、そのような機能の説得力のあるユースケースは知られていないため、デストラクタが適切なタイミングで実行されることを保証する重要な実装コストが発生します。
C++ 20以降、コンストラクタはconstexpr
とマークされる場合があります。 「デストラクタはconstexpr
の可能性があります」と具体的に記載されているかどうかはわかりませんが、 ドラフト標準 には、セクション9.2.5パラグラフ5に次のテキストが含まれています。
関数本体が
= delete
ではないconstexpr
デストラクタの定義は、さらに次の要件を満たします。
- クラス型またはその(多次元の)配列のサブオブジェクトごとに、そのクラス型にはconstexprデストラクタが必要です。
C++ 20はnew
コンテキストでdelete
とconstexpr
も許可し、vector
とstring
ハックなしでコンパイル時に機能する(C++ 20には、これを可能にする標準ライブラリへの変更が実際には含まれていないと思いますが、vector
と同じAPIと動作で何かを実装することは可能ですコンパイル時に完全に機能します)。