C++23では、この[[assume(expression)]]
属性により、表現の場合false
、動作は未定義です。例:
int div(int x, int y) {
[[assume(y == 1)]];
return x / y;
}
y
これは、常に の場合と同じコードにコンパイルされます1
。
div(int, int):
mov eax, edi
ret
しかし、もし別のレベル未定義の動作ですか?
int div(int x, int y) {
[[assume(x / 0 == 1)]];
return x / y;
}
現在、仮定内に UB がありますが、仮定は評価されていません。これはどういう意味ですか? これは単なるナンセンスですか、それともコンパイラーはこの仮定で何かできるのでしょうか?
ベストアンサー1
式は評価されません。
したがって、式の未定義の動作は、指定された入力によるプログラムの未定義の動作を直ちに意味するものではありません。
しかし、それは続きます:
変換された式が仮定が現れる時点で true と評価される場合、仮定は効果がありません。それ以外の場合、動作は未定義です。
未定義の動作をする式の評価は、評価される式の評価ではなくtrue
、プログラムの動作は「さもないと「文も同様、あるいは、それが不特定であると考える場合」変換された式が仮定が現れる時点で真と評価される場合「評価が未定義の動作をする場合、」が満たされる場合、「さもないと「」分岐が実行され、未指定の動作の 1 つの選択に対する未定義の動作は、全体として未定義の動作を意味するため、全体として再び未定義の動作が発生します。
これは提案書で具体的に取り上げられている。P17744.3 章では、仮定が に評価されない場合に動作を未定義にするという決定true
と、仮定が に評価される場合に動作を未定義にするという決定との間の微妙な違いとして説明しますfalse
。
この方法では、たとえば、x + y == z
コンパイラが符号付きオーバーフローの特殊なケースを考慮する必要がなくなり、最適化にその仮定を使用できなくなるような仮定を記述することが可能になります。