web-dev-qa-db-ja.com

constexpr関数本体c ++ 14に非リテラル型の定義変数を含めることができますか?

C++ 14では、constexprからより多くの制限が削除されていると思います。しかし、N3797 7.1.5によると3点:


Contexpr関数の定義は、次の制約を満たします。

  • それは仮想であってはならない
  • その戻り値の型はリテラル型でなければなりません。
  • その各パラメータタイプはリテラルタイプでなければなりません。
  • そのfunction-bodyは= 削除、= デフォルト、またはcompound-statement含まれていません:
    • asm-definition
    • a gotoステートメント、
    • atry-block、または
    • 非リテラル型、静的またはスレッドの保存期間、または初期化が実行されない変数の定義。

静的なスレッドストレージ期間変数が許可されていない理由はわかっていますが、理由はわかりません。リテラル型の変数の定義のみが許可されているのはなぜですか。

または私は標準を理解していません。

よくわかりませんが、標準に従って、C++ 14でも次のエラーが発生するはずです。

struct point{
constexpr point(): x(0), y(0){}
constexpr point(int x_, int y_): x(x_),y(y_){}
constexpr int hypot()const { return x*x + y*y; }
int x,y;
};

constexpr int hypot(int x, int y) {  
   point p{x,y}; //error, because p - is not literal type.
   return p.hypot();
}

// error, because return type is not literal.
constexpr point  getPoint(int x, int y) { return {x,y}; }

// error, because parameter is not literal.
constexpr int hypot(point p) { return p.hypot(); }

Q:本当に上記のエラーが発生する場合、なぜこれらの制限が削除されないのですか?

13
Khurshid

リテラルタイプは3.9/10で定義されています:

タイプはリテラルタイプの場合:

  • void;または

  • スカラー型。または

  • 参照型。または

  • リテラル型の配列。または

  • 次のすべてのプロパティを持つクラスタイプ(第9節):

    • 些細なデストラクタがあり、

    • 集計タイプ(8.5.1)であるか、コピーまたは移動コンストラクターではないconstexprコンストラクターまたはコンストラクターテンプレートが少なくとも1つあります。

    • その非静的データメンバーと基本クラスはすべて、不揮発性リテラルタイプです。

したがって、構造体pointisリテラル型であり、サンプルコードは有効なC++ 1yです。

constexpr関数がリテラル型の変数に制限されている理由については、コンパイル時に解釈可能であることが保証されているのはこれらの型だけです。

18
Casey