web-dev-qa-db-ja.com

デストラクタにconstexprをマークできないのはなぜですか?

C++では、多くのことを constexpr :変数、関数(メンバー関数と演算子を含む)、コンストラクターとして宣言できます。C++ 1z以降は ifステートメント および ラムダ式 。ただし、 destructorconstexprを宣言するとエラーが発生します。

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

私の質問:

  1. デストラクタにconstexprを付けることができないのはなぜですか?
  2. デストラクタを提供しない場合、暗黙的に生成されたデストラクタはconstexprですか?
  3. デフォルトのデストラクタ(~X() = default;)を宣言すると、自動的にconstexprになりますか?
34
s3rvac

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アップデート

C++ 20以降、ユーザー定義のデストラクタは、特定の条件下でconstexprになることもあります。

dcl.constexpr/

Constexpr関数の定義は、次の要件を満たす必要があります。

  • その戻り値の型(存在する場合)はリテラル型です。
  • それぞれのパラメーター型はリテラル型でなければなりません。
  • コルーチン([dcl.fct.def.coroutine])であってはなりません。
  • 関数がコンストラクタまたはデストラクタの場合、そのクラスには仮想基本クラスがあってはなりません。
  • その関数本体は([stmt.pre])を囲んではなりません。
    • gotoステートメント、
    • 識別子ラベル([stmt.label])、
    • 非リテラル型の変数の定義、または静的またはスレッドのストレージ期間。
14
Hemant Gangwar

あなたが探しているものが制限の背後にある理由である場合は、 この論文 を見てください。これは、制限が人工的なものであることを明確に示しています-constexprコンテキストでの動作を妨げるデストラクタの固有のプロパティはなく、実際コンパイラの実装者は、constexprコンテキストでそれらをサポートすることは簡単に実装できることに同意します

C++標準委員会は当初、C++ 11に制限を設けていたと思います。なぜなら、彼らはその時点でデストラクタを扱いたくなく、完全に除外する方が簡単だったからです。

5
saarraz1

デストラクタを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);
}
_
4
R Sahu

デストラクタをconstexprにすることはできません。これは、constexpr関数には副作用がなく、デストラクタは当然のことながら副作用によってのみ役立つためです。つまり、constexprのデストラクタを使用しても意味がありません。

デストラクタが自明でない場合、オブジェクトをconstexprにすることはできません。デフォルトのものは、取るに足らない場合、constexprと見なされます

ライブ

From [[class.dtor]

デストラクタ宣言のdecl-specifier-seqの各decl-specifier(存在する場合)は、friendinline、またはvirtualでなければなりません。

そこにありません、constexpr。だからあなたはそれを次のように取ることができます:標準がそう言っているのでTM

3
Passer By

参考 言う:

constexprデストラクタ

ほとんどの場合、定数式でT型のオブジェクトを作成するには、Tの破棄は簡単でなければなりません。ただし、重要なデストラクタは最近のC++の重要なコンポーネントです。これは、RAIIイディオムが広く使用されているためであり、これはconstexpr評価にも適用できます。次のように、自明ではないデストラクタを定数式でサポートできます。

  • デストラクタをconstexprとしてマークできるようにする
  • Constexprデストラクタのみを呼び出す場合、デフォルトのデストラクタをconstexprにする
  • Constexpr変数の場合、デストラクタの評価が定数式であることを要求します(破棄されるオブジェクトが独自のデストラクタで変更される可能性がある場合を除く)

ただし、そのような機能の説得力のあるユースケースは知られていないため、デストラクタが適切なタイミングで実行されることを保証する重要な実装コストが発生します。

2
msc

C++ 20以降、コンストラクタはconstexprとマークされる場合があります。 「デストラクタはconstexprの可能性があります」と具体的に記載されているかどうかはわかりませんが、 ドラフト標準 には、セクション9.2.5パラグラフ5に次のテキストが含まれています。

関数本体が= deleteではないconstexprデストラクタの定義は、さらに次の要件を満たします。

  • クラス型またはその(多次元の)配列のサブオブジェクトごとに、そのクラス型にはconstexprデストラクタが必要です。

C++ 20はnewコンテキストでdeleteconstexprも許可し、vectorstringハックなしでコンパイル時に機能する(C++ 20には、これを可能にする標準ライブラリへの変更が実際には含まれていないと思いますが、vectorと同じAPIと動作で何かを実装することは可能ですコンパイル時に完全に機能します)。

1
Cubic