Visual C++ 2010/2012/2013のバグとおぼしき挙動を見つけました。メンバ関数内において、ラムダ式の中からoperator()を呼び出そうとすると、なぜかラムダ式自身の呼び出しになります。

たとえばこんなコードで露呈します。

#include <iostream>
 
struct Hoge
{
  void test()
  {
    auto f = [&]{operator()();};
    f();
  }
  void operator()()
  {
    std::cout << "hoge" << std::endl;
  }
};
 
int main()
{
  Hoge obj;
  obj.test();
}

たとえば、これをコンパイルするとC4717警告(スタックオーバーフローが発生する旨)が指摘され、実行すると実際スタックオーバーフローが発生します。Hoge::test内のラムダ式内部でのoperator()呼び出しはHoge::operator()を意図しています。しかし、実際にはそのラムダ式自体の呼び出しになってしまうのです。すると、これは脱出口のない再帰呼び出しなので、スタックオーバーフローに一直線というわけです。

なお、GCCやClangでは期待通りに動作します。すなわち、Hoge::operator()の呼び出しになり、hogeを出力して正常終了する実行プログラムが出来上がります。


ちなみに、せっかくなのでこれで遊んでみました。再帰の定番である階乗です。

#include <iostream>
 
struct Hoge
{
  void test()
  {
    auto f = [&](int x) -> int {
      return x == 0
        ? 1
        : x * operator()(x - 1);
    };
    std::cout << f(5) << std::endl;
  }
 
  // 宣言さえあればコンパイル・実行できる
  int operator()(int);
};
 
int main()
{
  Hoge obj;
  obj.test();
}

これを実行すると、120が出力されます。ちゃんと5!が計算できていますね。


というわけで、Visual C++のバグらしい挙動でした。あとでバグ報告するために、まずはここにメモとして記録しておいています。

2014年1月19日追記:別の記事「Workaround: VC++のラムダ式とoperator()でのバグ?」で回避策を書きました。

スポンサード リンク

この記事のカテゴリ

  • ⇒ VC++のラムダ式とoperator()でのバグ?
  • ⇒ VC++のラムダ式とoperator()でのバグ?