次のコードは問題ありません。
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
誰かがその動作を説明できますか?
constexpr
以外のconst
変数は、定数式で使用できるように整数型または列挙型でなければなりません。 [expr.const]/2 を参照してください:
適用されない限り、左辺値から右辺値への変換
(2.7.1)不揮発性glvalueintegralまたはenumeration typeで初期化された完全な不揮発性constオブジェクトを参照し、定数式、または[..]
この制限の理由は、ほとんど歴史的なものでなければなりません。浮動小数点は、定数式に関して慎重に処理されています。型のないテンプレートパラメータだと思います。これは、コンパイル時の計算が本来よりも数学的になりにくい、プラットフォームに強く依存する動作によるものです。
定数式 (コア定数式)から:
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
を呼び出すことはできません。