C++11 std::bind関数バインド占拠パラメータstd::placeholders::1……
3102 ワード
C++の関数バインド機能を使用する場合、次の例のコードのように、毎回多くのプレースホルダを書く必要があります.
各バインディングは関数のパラメータ個数に応じて対応するビットパラメータを書く必要があり、個人的には面倒な感じがするので、これらのビットパラメータは省略したい.C++11のテンプレートパラメータが可変を許容する特性に基づいて,パラメータ個数を自動的に導出し,自動的に埋め込むためのコードを書いたが,非常に便利であった.独楽楽は衆楽楽に及ばず、分かち合ってみんなで使う.
C++11のautoは完全にタイプを自動的に導くことができないため,autoがタイプを返す関数の後にdecltypeを書く必要がある.C++14を使用すると、より簡潔になります.
この補助コードがあれば、前の例のコードのmain関数を次のように書き換えることができます.
さわやかになったのではないでしょうか.以上のコードはVS 2015およびGCC 4にある.9.3以上のバージョンのコンパイルにより、GCCは-std=c++11または-std=c++14パラメータを使用してコンパイルする必要があります.
おめでとうございます.
class CTest
{
public:
void foo1(int a, string& b, float c, double d, void* p);
void foo2(int a, string& b, float c, double d, void* p, short f);
};
int main()
{
CTest t;
// CTest::foo1 5 , 5
auto f1 = std::bind(&CTest::foo1, &t, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,std::placeholders::_4, std::placeholders::_5);
// CTest::foo1 6 , 6
auto f2 = std::bind(&CTest::foo2, &t, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3,std::placeholders::_4, std::placeholders::_5, std::placeholders::_6);
return 0;
}
各バインディングは関数のパラメータ個数に応じて対応するビットパラメータを書く必要があり、個人的には面倒な感じがするので、これらのビットパラメータは省略したい.C++11のテンプレートパラメータが可変を許容する特性に基づいて,パラメータ個数を自動的に導出し,自動的に埋め込むためのコードを書いたが,非常に便利であった.独楽楽は衆楽楽に及ばず、分かち合ってみんなで使う.
#if _MSC_VER
#define PlaceHolder std::_Ph
#else
#define PlaceHolder std::_Placeholder
#endif
template
struct MakeSeqs : MakeSeqs {};
template
struct MakeSeqs<1, I...>
{
template
static auto bind(T* obj, R(T::*_Func)(Args...)) -> decltype(std::bind(_Func, obj, PlaceHolder{}...))
{
return std::bind(_Func, obj, PlaceHolder{}...);
}
};
template
auto Bind(T* t, R(T::*f)(Args...)) -> decltype(MakeSeqs::bind(t, f))
{
return MakeSeqs::bind(t, f);
}
template
auto Bind(R(T::*f)(Args...), T* t) -> decltype(MakeSeqs::bind(t, f))
{
return MakeSeqs::bind(t, f);
}
C++11のautoは完全にタイプを自動的に導くことができないため,autoがタイプを返す関数の後にdecltypeを書く必要がある.C++14を使用すると、より簡潔になります.
#if _MSC_VER
#define PlaceHolder std::_Ph
#else
#define PlaceHolder std::_Placeholder
#endif
template
struct MakeSeqs : MakeSeqs {};
template
struct MakeSeqs<1, I...>
{
template
static auto bind(T&& obj, _Fx&& _Func)
{
return std::bind(std::forward<_fx>(_Func), std::forward(obj), PlaceHolder{}...);
}
};
template
auto Bind(T* t, R(T::*f)(Args...))
{
return MakeSeqs::bind(t, f);
}
template
auto Bind(R(T::*f)(Args...), T* t)
{
return MakeSeqs::bind(t, f);
}
この補助コードがあれば、前の例のコードのmain関数を次のように書き換えることができます.
int main()
{
CTest t;
auto f1 = Bind(&CTest::foo1, &t);
auto f2 = Bind(&CTest::foo2, &t);
return 0;
}
さわやかになったのではないでしょうか.以上のコードはVS 2015およびGCC 4にある.9.3以上のバージョンのコンパイルにより、GCCは-std=c++11または-std=c++14パラメータを使用してコンパイルする必要があります.
おめでとうございます.