この記事はLambda その2の続編です。
その後C++0xの規格案は変化し、変数のキャプチャをしないラムダ式は、関数へのポインタへ変換できることになりました。
1 2 3 4 5 6 7 8 | int main() { int x; typedef void (*pf_t)(); pf_t pfOK = [](){}; // OK! pf_t pfNG = [x](){}; // コンパイルエラー } |
というわけで、以前のラムダ式のコードもこう書けるようになりました。あのときは「キャプチャなし(外側の環境の影響を一切受けないもの)でも関数へのポインタに変換するのは駄目でしたね」なんて書いていましたが。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | #include <iostream> #include <string> #include <deque> #include <algorithm> #include <functional> #define WIN32_LEAN_AND_MEAN #include <windows.h> namespace egtra { typedef std::function<bool (HWND)> enum_func_t; inline BOOL EnumWindows(enum_func_t fn) { return ::EnumWindows([](HWND hwnd, LPARAM lp) -> BOOL { return (*reinterpret_cast<enum_func_t*>(lp))(hwnd); }, reinterpret_cast<LPARAM>(&fn)); } std::basic_string<TCHAR> GetWindowText(HWND hwnd) { std::basic_string<TCHAR> s; if (int tmpLen = GetWindowTextLength(hwnd)) { ++tmpLen; s.resize(static_cast<size_t>(tmpLen)); int len = GetWindowText(hwnd, &s[0], tmpLen); s.resize(len); } return s; } } int main() { std::deque<HWND> hwnds; egtra::EnumWindows([&hwnds](HWND hwnd) -> bool { hwnds.push_back(hwnd); return true; }); std::for_each(hwnds.begin(), hwnds.end(), [](HWND hwnd) { std::cout << std::hex << hwnd << '\t' << egtra::GetWindowText(hwnd) << std::endl; }); } |
小さな変化ですが、std::tr1::functionがstd::functionになっています。
さて、EnumWindowsに渡す関数は呼出規約Stdcallでないといけません。ただ、ラムダ式に対しては呼出規約を指定できないようです(そんな構文ないです)。というわけで、現状ではコンパイルオプションで指定するしかないと思います。ちょっと残念なオチですね。
g++ -std=c++0x -mrtd enumwindow.cpp
GCC 4.5.2で試しました。なお、-mrtdの本家解説はこちらです: i386 and x86-64 Options – Using the GNU Compiler Collection (GCC)。
スポンサード リンク |