C ++には定数式の非常にきちんとした特性があります。それらの評価に未定義の動作を含めることはできません(7.7.4.7):
抽象マシン([intro.execution])の規則に従ってeの評価が次のいずれかを評価しない限り、式eはコア定数式です。
...
このドキュメントの[intro]から[cpp]で指定されている未定義の動作を持つ操作[注:たとえば、符号付き整数オーバーフロー([expr.prop])、特定のポインター演算([expr.add])、ゼロによる除算、または特定のシフト演算—後記];
値を格納しようとする13!
中でconstexpr int
実際には、素敵なコンパイルエラーを生成します:
constexpr int f(int n)
{
int r = n--;
for (; n > 1; --n) r *= n;
return r;
}
int main()
{
constexpr int x = f(13);
return x;
}
出力:
9:19: error: constexpr variable 'x' must be initialized by a constant expression
constexpr int x = f(13);
^ ~~~~~
4:26: note: value 3113510400 is outside the range of representable values of type 'int'
for (; n > 1; --n) r *= n;
^
9:23: note: in call to 'f(3)'
constexpr int x = f(13);
^
1 error generated.
(ところで、エラーがf(13)の呼び出しであるのに、「call to 'f(3)'」と表示されるのはなぜですか?)
次に、から削除constexpr
しますx
が、を作成f
しconsteval
ます。ドキュメントによると:
consteval-関数が即時関数であることを指定します。つまり、関数を呼び出すたびにコンパイル時定数を生成する必要があります。
私はそのようなプログラムが再びコンパイルエラーを引き起こすことを期待しています。しかし代わりに、プログラムはUBでコンパイルおよび実行されます。
何故ですか?
UPD:コメンターは、これがコンパイラのバグであると提案しました。私はそれを報告しました:https://bugs.llvm.org/show_bug.cgi?id = 43714
in call to 'f(3)'
- これは奇妙です!例 あなたがf(123)
clang を置く場合について警告しin call to 'f(119)'
ます。