Boost.Coroutine
Google Summer Of Code 2006(SoC 2006)のプロジェクトの一つとして、C++でコルーチンを使えるようにするBoost.Coroutineというものがあります。
http://lists.boost.org/Archives/boost/2006/08/109369.php
これを使えば、ここやここで議論していた列挙コールバック関数の反復子化が簡単に実現できます。
#include <boost/coroutine/generator.hpp> #include <boost/bind.hpp> #include <iostream> #include <string> #include <windows.h> namespace coro = boost::coroutines; typedef coro::generator< ::HWND> hwnd_generator; // EnumWindows()/EnumChildWindows()共通コールバック ::BOOL CALLBACK enum_windows_proc(::HWND hwnd, ::LPARAM lParam) { try { hwnd_generator::self& self = *reinterpret_cast<hwnd_generator::self*>(lParam); self.yield(hwnd); // ここでコンテキストが切り替わる return TRUE; } catch (...) { // 途中で反復をやめた場合はexit_exceptionが飛んでくる } return FALSE; } ::HWND enum_windows_generator(hwnd_generator::self& self) { ::EnumWindows(&enum_windows_proc, reinterpret_cast< ::LPARAM>(&self)); self.exit(); } ::HWND enum_child_windows_generator(hwnd_generator::self& self, ::HWND parent) { ::EnumChildWindows(parent, &enum_windows_proc, reinterpret_cast< ::LPARAM>(&self)); self.exit(); } // いい加減なGetWindowText() std::string get_window_text(::HWND hwnd) { char buf[256]; ::GetWindowText(hwnd, buf, sizeof(buf)); return buf; } int main() { // 引数なし { hwnd_generator generator(enum_windows_generator); while (generator != hwnd_generator()) std::cout << get_window_text(*generator++) << '\n'; } // 1引数の場合(bindするだけ) { ::HWND desktop = ::GetDesktopWindow(); hwnd_generator generator( boost::bind(enum_child_windows_generator, _1, desktop)); while (generator != hwnd_generator()) std::cout << get_window_text(*generator++) << '\n'; } }
Boostに受理されるのが待ち遠しいです。
なお、Windows版の実装にはFiberが用いられているため、_WIN32_WINNT>=0x0400、WINVER>=0x0400でコンパイルする必要があります。