2017-07-27 5 views
1
int d = 1; 
constexpr void add() 
{ 
    d++; 
} 

int main() 
{ 

} 

GCC 7.1は以下のエラーを報告します。エラーメッセージは非常に明確です。問題は、私がconstexprに明示的に説明していることが違法であるとは言いません。constexpr非メンバ関数のグローバル非定数変数にアクセスするのがなぜ合法でないのですか

誰かがこのルールで定義されているルールが違反していると説明できますか?

 

main.cpp: In function 'constexpr void add()': 

main.cpp:8:1: error: the value of 'd' is not usable in a constant expression 

} 

^ 

main.cpp:4:5: note: 'int d' is not const 

int d = 1; 

    ^
+5

「このような関数の呼び出しその引数の値の少なくとも1つのセットが存在しますコア定数式 " –

+0

の評価された部分式かもしれません。オブジェクトが不揮発性のリテラルタイプを持ち、その寿命が式の評価内で始まらない限り、オブジェクトの変更はルール#16を破るようです。しかし、私がconstexpr void add()に変更した場合 { d = 2; }それは通過できます。 – Kane

+0

clangのエラーメッセージが明白に見えますが、定数式ではその式の外側に表示されているオブジェクトを変更できません。しかし、私はまだそれが壊れているルールを見つけることができませんhttp://en.cppreference.com/w/cpp/language/constant_expression#Core_constant_expressions – Kane

答えて

0

コメントは標準参照の観点からはうまくいきますが、ここではよりわかりやすく説明してください。

constexpr関数はコンパイル時に定数式に縮小可能でなければなりません。関数内の通常の非constintと対話しているため、コンパイラはどのような状況でもd++が何であるかを判断できません。以下のケースを考えてみましょう:

この場合
int d; 
constexpr void add() { 
    d++; 
} 

void foo() { 
    int n; 
    std::cin >> n; 
    d = n; 
    add(); 
} 

foo()内部dの値はコンパイル時に不確定であるため、あなたとあなたを残してadd()を期待している定数式を決定することはできません。私はそれが助けて欲しい

+0

それは本当ではありません。 constexprは、すべての前提条件が満たされた場合にのみ意味し、コンパイル時に評価されます。それ以外は動的に実行されます。 – Kane

2

cppreferenceより:

コア定数式は、任意のサブ式で、次のいずれか(例えばはsizeofのオペランド又は& &を組み込みの右オペランドとして未評価の式を無視していない任意の式であります左のオペランドが偽と評価されたとき)。

...

16)オブジェクトの変更、オブジェクトが非揮発性リテラルタイプとその寿命は、式の評価中に始まっていない限り。あなたの例では

daddが評価された前の寿命が始まった - そうadd内部dのいずれかの変更が違法です。参照の例は、特にインクリメント用ですが、これはすべての変更に適用されます。

編集:限り、私は承知しているとして、あなたはそれを購入するために持っているので、標準から引用していない...

+0

私は生涯が理由だと思ったが、GCC7.1はこのケースでは不平を言っていない、http://coliru.stacked-crooked.com/a/d4e544c05b187b03。もしd = 2がd + = 2に変更されれば、それは不平を言うでしょう。さらに、同じコードは常にclangで失敗します。http://coliru.stacked-crooked.com/a/5d83921f7f0e871b – Kane

関連する問題