この記事は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)


スポンサード リンク

この記事のカテゴリ