13

このコードが GCC (4.9 および 5+) でコンパイルされるのに、clang (3.5-3.9) ではコンパイルされないのはなぜですか?

void test(const int&) { }
int main() {
  const int x = 42;
  auto f = []{ test(x); };
}

不一致が ODR (One Definition Rule) の使用に関係しているという漠然とした考えがありますが、ここで何が起こっているのかを理解するのに十分ではありません。

4

2 に答える 2

16

xtest参照 (のパラメーター)にバインドされているため、odr で使用されます。したがって、キャプチャする必要があります ( [expr.prim.lambda]/13 ):

ラムダ式またはジェネリック ラムダの関数呼び出し演算子テンプレートのインスタンス化が ODR を使用する場合([basic.def.odr]) this 、または到達範囲からの自動保存期間を持つ変数の場合、そのエンティティはラムダによってキャプチャされるものとします。 -式.

この規則の違反は、「診断は必要ありません」または「未定義の動作」とは言わない標準の他のすべての規則と同様に、診断が必要です

残念ながら、GCC はコンスタント フォールディングを実行するのが早すぎて、それが ODR 使用かどうかを判別できません。これにより、ダングリング参照が返されるなどの[&]()->const int & { return x; }問題が発生する可能性があります。

于 2016-03-17T21:27:10.410 に答える
8

TC には正しい診断があります。clang は正しいことを行い、gcc はそうではない、より明確な法的なコードを次に示します。

#include <iostream>

void test(const int&a) { std::cout << "in test() -- " << &a << "\n"; }
int main() {
  const int x = 42;
  std::cout << "in main() -- " << &x << "\n";
  auto f = [&]{ test(x); };
  f();
}

gcc は、参照によるキャプチャー変数のアドレスを元のアドレスとは異なるものとして出力します!

于 2016-03-17T21:40:52.973 に答える