web-dev-qa-db-ja.com

const変数の値は、変数のタイプに応じて、定数式で使用可能または使用不可です

次のコードは問題ありません。

constexpr double square_cstxpr(double x) { return x * x; }

int main() {
    const int test = 5;
    constexpr double result = square_cstxpr((double)test);
}

ただし、testのタイプがconst intからconst doubleに変更された場合、g ++は次のエラーを返します:the value of 'test' is not usable in a constant expression

ここでg ++のコードと出力を参照してください: http://coliru.stacked-crooked.com/a/2fe9b176c2b23798

誰かがその動作を説明できますか?

13
Georg

constexpr以外のconst変数は、定数式で使用できるように整数型または列挙型でなければなりません。 [expr.const]/2 を参照してください:

適用されない限り、左辺値から右辺値への変換

(2.7.1)不揮発性glvalueintegralまたはenumeration typeで初期化された完全な不揮発性constオブジェクトを参照し、定数式、または[..]

この制限の理由は、ほとんど歴史的なものでなければなりません。浮動小数点は、定数式に関して慎重に処理されています。型のないテンプレートパラメータだと思います。これは、コンパイル時の計算が本来よりも数学的になりにくい、プラットフォームに強く依存する動作によるものです。

6
Columbo

定数式 (コア定数式)から:

10)左辺値が...でない限り、他の左辺値から右辺値への暗黙的な変換.

a)整数型または列挙型を持ち、定数式で初期化される完全な不揮発性constオブジェクトを参照します

つまり、ここで:

const int test1 = 5;
constexpr double result1 = square_cstxpr((double)test1);

test1は定数式です。square_cstxprは、コンパイル時にtest1を引数として呼び出し、その結果をconstexpr変数に割り当てることができますresult

一方、ここで:

const double test2 = 5;
constexpr double result2 = square_cstxpr((double)test2);

test2は、整数型または列挙型ではないため、定数式ではありません。そのため、square_cstxprを引数としてコンパイル時にtest2を呼び出すことはできません。

7
Edgar Rokjān