web-dev-qa-db-ja.com

以下のコードは、不正なNDRですか、それとも整形式ですか?

Clangは次のコードを受け入れますが、gcc 拒否 です。

_void h() { }

constexpr int f() {
    return 1;
    h();
}

int main() {
    constexpr int i = f();
}
_

エラーメッセージは次のとおりです。

_g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
main.cpp: In function 'constexpr int f()':
main.cpp:5:6: error: call to non-'constexpr' function 'void h()'
     h();
     ~^~
main.cpp: In function 'int main()':
main.cpp:9:24: error: 'constexpr int f()' called in a constant expression
     constexpr int i = f();
                       ~^~
main.cpp:9:19: warning: unused variable 'i' [-Wunused-variable]
     constexpr int i = f();
_

[dcl.constexpr]/5 を検討すると、f()は定数式ではないため、これは両方のコンパイラーが正しい場合である可能性があります。 constexpr以外の関数hを呼び出すため、 [expr.const] /(4.2) を満たします。つまり、コードの形式は正しくありませんが、診断は必要ありません。

もう1つの可能性は、[expr.const] /(4.2)がこの場合適用されないため、コードの形式が正しいことです。これは、hfへの呼び出しが評価されないためです。この場合、gccは間違っており、clangは正しいです。

24
Alexander

Clangは正しいです。 f()の呼び出しは評価されないため、h()の呼び出しは定数式であり、[dcl.constexpr]/5は適用されません。 h()の本体にあるf()の呼び出しは、constexpr関数の constraints が何も言っていないため、形式が正しくありません非constexpr関数の呼び出しは許可されていません。実際、xが奇数の場合、その呼び出しは定数式になる可能性があるため、次のような関数は整形式です。

constexpr int g(int x) {
    if (x%2 == 0) h();
    return 0;
}
24
Brian