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()でのバグ?」で回避策を書きました。
スポンサード リンク |