Visual C++ 2015から、std::bindとstd::mem_fnがデフォルト以外の呼出規約の関数に対応しました。

#include <iostream>
#include <functional>
 
void __stdcall fs(int i)
{
  std::cout << i << std::endl;
}
 
void __fastcall ff(const char* s)
{
  std::cout << s << std::endl;
}
 
int main()
{
  auto x = std::bind(fs, 1);
  auto y = std::bind(ff, "mikan");
  x();
  y();
}

C++/CLIとしてコンパイルする場合、__fastcallの代わりに__clrcallが使えるようになります。

mem_fnの例です。メンバ関数のデフォルトは__thiscallなので、新たに__cdeclや__stdcallの関数を渡せることになります。

class hoge
{
public:
  void __cdecl f() {}
};
 
int main()
{
  std::mem_fn(&hoge::f);
}

__stdcallのメンバ関数の例です。私自身、COMインタフェースの関数をbindやmem_fnした経験があります。

#include <functional>
#include <memory>
#include <shlwapi.h>
 
int main()
{
  std::shared_ptr<IStream> p(
    SHCreateMemStream(nullptr, 0),
    std::mem_fn(&IUnknown::Release));
}

なお、Boostのbindとmem_fnでは、以前より特定の#define定義で、呼び出し規約付きの関数が使えるようになっていました。__stdcall, __cdecl, __fastcall, and pascal Support

  • BOOST_BIND_ENABLE_STDCALL, BOOST_MEM_FN_ENABLE_STDCALL
  • BOOST_BIND_ENABLE_FASTCALL, BOOST_MEM_FN_ENABLE_STDCALL
  • BOOST_BIND_ENABLE_STDCALL, BOOST_MEM_FN_ENABLE_FASTCALL
  • BOOST_BIND_ENABLE_PASCAL
  • BOOST_MEM_FN_ENABLE_CDECL

Visual C++ 2015のほうは、とくに何も定義しなくても各種呼出規約の関数を扱えるようになっています。

今のVisual C++はpascal呼出規約に対応していないので、Visual C++のstd::bindとstd::mem_fnはx86(32ビット)のVisual C++で使える呼出規約一通りに対応したことになります。

以上、Visual C++ 2015のstd::bindとstd::mem_fnが__stdcall, __fastcall, __clrcallの関数に対応した話でした。なお、私、過去これが理由でboost::bindやboost::mem_fnを使った場面が実際ありました。そのため、今回の対応で大変便利になったと思っています。


スポンサード リンク

この記事のカテゴリ

  • ⇒ VC++ 2015のbindとmem_fnは呼出規約付きの関数を扱える
  • ⇒ VC++ 2015のbindとmem_fnは呼出規約付きの関数を扱える