2016-01-21 8 views
5

次のコードは、gcc 5.3.0で正常にコンパイルされましたが、clang 3.7.0でコンパイルできませんでした。私は両方の場合に同じコマンドラインオプションを使ってオンラインcoliruコンパイラを使用しました:-std = C++ 14 -O2 -Wall -pedantic -pthread。constexpr関数本体内の評価されていないコンテキストでのみ使用される引数

#include <cstdio> 

// Definition of constexpr function 'foo'. 
constexpr std::size_t foo(const int& arg_foo) { return sizeof(arg_foo); } 

// Definition of function 'test'. 
void test(const int& arg) 
{ 
    // The following line produces an error with clang. 
    constexpr std::size_t res_foo = foo(arg); 

    // Print the result returned by the 'foo' function. 
    std::printf("res_foo = %lu\n", res_foo); 
} 

// Definition of function 'main'. 
int main(int argc, const char* argv[]) 
{ 
    // Test function call. 
    test(argc); 

    // Return statement. 
    return 0; 
} 

打ち鳴らすには、次のエラーでそれを拒否:これは、コードの有効な部分である場合、私は疑問に思って、そのため2つのコンパイラとのこの違いの

error: constexpr variable 'res_foo' must be initialized by a constant expression 
constexpr size_t res_foo = foo(arg); 
          ~~~~^~~~ 

。そうでない場合は、なぜこれが当てはまるのかをよりよく理解したいと思います。

+0

gcc bug、constexprについては多くの人のうちの1人 – TemplateRex

+0

@TemplateRexしかし、 'foo'はどのようにしてconstexpr関数の規則を破りますか? – Archimaredes

+0

@Archimaredesいいえ、 'test'の' arg'は 'constexpr'ではありません – TemplateRex

答えて

1

constconstexprの値を混在させています。 constexprの定義は、コンパイル時にわかっている値です。しかし、argc変数は実行時にのみ認識されます(実行可能ファイルに渡される引数の数です)。したがって、他のconstexpr変数 - res_fooに割り当てることはできません。 res_foo定義からconstexprを削除すると、コードがコンパイル可能になります。

constconstexprの違いは、このような何かを簡素化することができます。
const - 私は、この値
constexprを変更するつもりはない - この値は、私はつもりはないコンパイル時で知られていますそれを変更する

私は、arg_foo引数を使用しておらず、コンパイル時にGCCがO2でこのコードをコンパイルできると思います。しかし、それでも文法的には間違っています。非constexpr値がconstexpr変数に割り当てられているため、コンパイラはエラーを出すべきです。

+1

彼はこれを知っていると思います、彼の質問は実際には' argc'の値を使用していないので、 'sizeof 'は定数式です。 – TartanLlama

+0

@TartanLlamaなぜgccはO2でこのコードをコンパイルできるのですか?gccはこのコードを使用しないので引数を無視し、よく知られているコンパイル時の値を返します。しかしそれは構文的には間違っています。コンパイラは'constexpr'以外の値が 'constexpr'変数に割り当てられているので、エラーを出さなければなりません。 – DennisS

+0

私はそれがまだ構文的に間違っていることを知っていますが、私はあなたが答えで対処すべきものだと思います。 – TartanLlama

0

foo(arg)は、C++ 14 5.20/2で定義されているような正価のコア定数式であるため、プログラムは整形式です。特に、評価中に左辺値と右辺値の変換はなく、定数式ではありません。

+0

それを評価するには、[expr.const] /2.9を実行している* id-expression * 'arg'を評価する必要があります。" 抽象規則に従ってeを評価しない限り、条件式eはコア定数式です[...]参照が先行する初期化を持たず、かつ定数式で初期化されない限り、参照型の変数またはデータメンバを参照するid式または、e "の評価内で寿命が始まったオブジェクトの非静的データメンバーです。 –

+0

5/8 "未評価のオペランドは評価されません。" – aschepler

+0

はい、 'foo'の中で評価されません。しかし、それは議論の通過のために外で評価されています。 'foo(arg)'を評価する最初のステップは 'foo'と' arg'を評価することです。 –

関連する問題