gcc 4.5 では、次のコードがコンパイルされ-std=c++0x
、期待どおりに動作します。
#include <stdio.h>
template<typename H>
void caller(H h)
{
h();
}
int main()
{
auto c = [](){ printf("A\n"); };
caller(c);
caller([](){ printf("B\n"); });
return 0;
}
プリント、
A
B
ただし、caller
が参照を取るように定義されている場合、
template<typename H>
void caller(H &h)
{
h();
}
コンパイラは不平を言います、
test.cpp: In function ‘int main()’:
test.cpp:61:34: error: no matching function for call to ‘caller(main()::<lambda()>)’
test.cpp:52:6: note: candidate is: void caller(H&) [with H = main()::<lambda()>]
なんで?
これは、ラムダが関数に値のセマンティクスを提供するという考えを破るように見えますが、さらに、特定の小さな関数をインラインで記述できないことを意味し、これは少し面倒です。
(これは gcc の新しいバージョンで修正されていますか? テストする機会がありませんでした。)
編集:以下が実際に機能することを発見しました:
template<typename H>
void caller(H *h)
{
(*h)();
}
int main()
{
auto c = [](){ printf("A\n"); };
caller(&c);
caller(&([](){ printf("B\n"); }));
}
そんな仮のアドレスが取れるとは思わなかった。関数のユーザーに、便利な参照の代わりにクロージャのアドレスを渡すように要求するのは面倒ですが、おそらくそのような問題は解決します。