2015-12-15 5 views
18

次のコードはclang ++ 3.7.0でコンパイルされますが、g ++ 5.3.1では拒否されます。どちらも-std=c++14オプションがあります。どのコンパイラが正しいですか?誰でも、標準についてどこでこれについて話すのか知っていますか?ありがとう。constexpr関数をスローする

#include <stdexcept> 
using namespace std; 

constexpr int f(int n) { 
    if (n <= 0) throw runtime_error(""); 
    return 1; 
} 

int main() { 
    char k[f(1)]; 
} 

出力

[hidden] g++ -std=c++14 c.cpp 
c.cpp: In function ‘constexpr int f(int)’: 
c.cpp:7:1: error: expression ‘<throw-expression>’ is not a constant-expression 
} 
^ 
[hidden] clang++ -std=c++14 c.cpp 
[hidden] 
[hidden] g++ -v 
Using built-in specs. 
COLLECT_GCC=/usr/bin/g++ 
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/5.3.1/lto-wrapper 
Target: x86_64-redhat-linux 
Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --disable-libgcj --with-isl --enable-libmpx --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux 
Thread model: posix 
gcc version 5.3.1 20151207 (Red Hat 5.3.1-2) (GCC) 
[hidden] 
[hidden] clang++ -v 
clang version 3.7.0 (http://llvm.org/git/clang.git 2ddd3734f32e39e793550b282d44fd71736f8d21) 
Target: x86_64-unknown-linux-gnu 
Thread model: posix 
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/3.4.6 
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/5.3.1 
Selected GCC installation: /usr/lib/gcc/x86_64-redhat-linux/5.3.1 
Candidate multilib: .;@m64 
Candidate multilib: 32;@m32 
Selected multilib: .;@m64 
+0

標準のdoesnに:

constexpr auto foo(int n) -> int { return n <= 0 ? throw runtime_error("") : 1; } 

は、しかし、まだc++14 constexprの拡張子のすべてを保持より良い回避策があり、私が見ることができる限り、投げることはできないと言っています –

+0

これにはgccのバグレポートがあり、回避策はありません。 –

答えて

15

打ち鳴らすが正しいか、HEAD revision of gcc acceptsもこのコードを受け入れ注意してください。これは、関数がコア定数式として評価されることを可能にする引数の値が存在する限り、整形式のconstexpr関数です。あなたの場合、1はそのような値です。

これはC++ 14標準セクション7.1.5 constexprの機能で許されているものを教えてくれるconstexprの指定子[dcl.constexpr]ドラフトで覆われている:

constexprの関数の定義は満足しなければなりません次の制約:

  • 仮想(10.3)でないものとします。

  • リターンタイプはリテラルタイプでなければなりません。

  • それぞれのパラメータ型はリテラル型でなければなりません。

  • その機能-体は=デフォルト、または

    • ASM-定義、

    • goto文、

    • を含まない化合物文、削除しなければなりません=
    • トリブロックまたは

    • 変数の非リテラル型または静的またはスレッド型stの変数の定義または初期化が実行されない。 throw

制限なし、それはまた言う(強調鉱山):非テンプレート、非ディフォルトconstexprの機能または非テンプレートについては

、非デフォルト、非継承 constexprコンストラクタ引数または値が存在しない場合は、関数またはコンストラクタの呼び出し が評価者になる可能性がありますコア定数式(5.19)の副次表現では、プログラムは不正である;いいえ 診断が必要です。

とこの段落の下に、私たちはあなたに似た次の例を、持っている:

constexpr int f(bool b) 
    { return b ? throw 0 : 0; } // OK 
constexpr int f() { return f(true); } // ill-formed, no diagnostic required 

throwセクション5.19で覆われているコア定数式で許可されていない[expr.constを]段落2となり、

条件式e

  • :次の式の1

を評価し、次の箇条書きが含まれてしまう、 抽象機械(1.9)の規則に従って、Eの評価をしない限り、コア定数式ですスロー式(15.1)。

のでfコア定数式n <= 0で使用可能ではないであろう。

更新

TemplateRexが指摘するように、このための2つのGCCのバグレポートがあります

TemplateRexも修正が適用されていないノート〜5.3.0にあり、トランク内にのみ存在します。いいえ、回避策が用意されています。

4

これは、Shafik Yaghmourで示されているように、gccバグです(v6でうまくいけばうまくいきます)。

それまでは、c++11 constexprのスタイルに戻すことができます:

// or maybe name it 
// throw_if_zero_or_less 
constexpr auto foo_check_throw(int n) -> void 
{ 
    n <= 0 ? throw std::runtime_error("") : 0; 
} 

constexpr auto foo(int n) -> int 
{ 
    foo_check_throw(n); 

    // C++14 extensions for constexpr work: 
    if (n % 2) 
    return 1; 
    return 2; 
} 
関連する問題