次の例を考えてみます(スニペット(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には実際のバグがありました)。