次の例を考えてみます(スニペット(0)):
struct X
{
constexpr int get() const { return 0; }
};
void foo(const X& x)
{
constexpr int i = x.get();
}
int main()
{
foo(X{});
}
上記の例は、g++
以前のすべてのバージョンでコンパイルされg++ 10.x
、でコンパイルされることはありませんclang++
。エラーメッセージは次のとおりです。
error: 'x' is not a constant expression 8 | constexpr int i = x.get(); |
ただしx
、の本体で定数式が使用されることはないため、エラーの種類には意味がありますfoo
。
X::get()
マークされてconstexpr
おり、の状態には依存しませんx
。に変更
const X&
するconst X
と、コードは(godbolt.org上の) すべてのコンパイラスニペット(1)でコンパイルされます。
私はマークしたときには、さらに面白いX::get()
とstatic
(()godbolt.org上の スニペット(2) )。この変更により、g++
(トランクを含む)すべてのテスト済みバージョンがコンパイルされますが、コンパイルはclang++
常に失敗します。
だから、私の質問:
スニペット(0)の
g++ 9.x
受け入れは正しいですか?すべてのコンパイラーがスニペット(1)を受け入れるのは正しいですか?もしそうなら、なぜ参照は重要ですか?
ある
g++ 9.x
とg++ trunk
受け入れることで正しいスニペット(2) ?
x
でfoo
はありません。clangの正しい動作に関する古い(非公式に拒否された)バグレポートさえあります(GCCには実際のバグがありました)。