2016-05-26 6 views
3

引数を開いたままメンバ関数をオブジェクトにバインドしようとしています。私はラムダ式(例えばthis)でラップすることでそれを行うことができますが、私はstd :: bindとstd :: placeholdersを使ってそれをやりたいC++でメンバ関数をオブジェクトにバインドする方法14

これまでのところ、これは私が持っているものです:>私はSTDを呼び出すときにplace_holdersのタプルを作成

template <size_t _Num> 
struct place_holder {}; 

namespace std { 
    template <size_t _Num> 
    struct is_placeholder<::place_holder<_Num>> : integral_constant<size_t, _Num> {}; 
} 

namespace _binding_helper_ { 
    template <size_t ... _Indices> 
    std::tuple<place_holder<_Indices>...> get_placeholders(std::index_sequence<_Indices...>) { 
     return std::make_tuple(place_holder<_Indices>()...); 
    } 
} 

template <typename _Obj, typename _Func, typename ... _Args> 
std::function<_Func(_Args...)> bind_function_to_object 
    (_Func (_Obj::*func)(_Args...), _Obj & obj) { 
    return std::bind(func, obj, 
     _binding_helper_::get_placeholders(std::make_index_sequence<sizeof...(_Args)>{})); 
} 

が正常に動作しますが、:: < is_placeholder ::彼らはすべてしているタプルの要素の値私はどのようにしてplaceholderを初期化することができます< _Num> _Numのすべての必要な値の構造体をstd :: placeholdersとして初期化できますか?簡単な修正があることを願っています。どんな助けもありがたい。ありがとう!

+1

あなたは、テンプレートをインスタンス化する方法のサンプルを表示することができます。 –

+0

'is_placeholder'は' integral_constant 'ではなく、' integral_constant 'から継承する必要があります。 – ildjarn

+0

私は 'obj'の代わりに' std :: bind'に 'obj'のアドレスを渡したいと思うでしょう。 – Zack

答えて

2

プレースホルダには1の番号が付けられ、0ではありません。私はあなたが言及した理由のためにあなたのstatic_assertが条件std::is_placeholder<place_holder<0>>{}であることに失敗したと推測します。

また、プレースホルダーのタプルをstd::bindに渡しています。代わりに、プレースホルダを直接渡す必要があります。つまり、place_holder<Is + 1>{}...です。

template <int Num> 
struct place_holder {}; 

namespace std 
{ 
    template <int Num> 
    struct is_placeholder<::place_holder<Num>> : integral_constant<int, Num> {}; 
} 

template <typename Obj, typename C, typename Func, typename... Args, int... Is> 
std::function<Func(Args...)> bind_function_to_object(Func(C::*func)(Args...), Obj&& obj, std::integer_sequence<int, Is...>) 
{ 
    return std::bind(func, std::forward<Obj>(obj), place_holder<Is + 1>{}...); 
} 

template <typename Obj, typename C, typename Func, typename... Args> 
std::function<Func(Args...)> bind_function_to_object(Func(C::*func)(Args...), Obj&& obj) 
{ 
    return bind_function_to_object(func, std::forward<Obj>(obj), std::make_integer_sequence<int, sizeof...(Args)>{}); 
} 

DEMO

+0

華麗な、トリックをやった!どうもありがとう!余分なテンプレートタイプCなしでそれを行う方法はありますか?基本的に同じタイプのオブジェクトを記述する2つのテンプレートパラメータを持つことは奇妙に思えます。 – geanakuch

+1

@geanakuchベースクラスのメンバ関数と派生クラスのインスタンスを渡すことができます。それが気に入らないのであれば、完璧なフォワードを削除し、左辺値参照、つまり 'Obj&obj'、'(Obj :: * func) 'などを使用してください。 –

関連する問題