2012-02-08 18 views
4

クラスFooに構造上の関数ポインタを格納させ、ある時点でこの関数を呼び出すようにします。私は助けのためにこれら二つの質問を見て:関数を呼び出してタプルに格納されたパラメータを渡すか?

#include <functional> 

template < int N, typename... ARGS > 
struct apply_func { 
    static void applyTuple(std::function<void(ARGS...)>& f, 
          const std::tuple<ARGS...>& t, 
          ARGS... args) { 
    apply_func<N-1>::applyTuple(f, t, std::get<N-1>(t), args...); 
    } 
}; 

template <typename... ARGS> 
struct apply_func<0,ARGS...> 
{ 
    static void applyTuple(std::function<void(ARGS...)>& f, 
          const std::tuple<ARGS...>& /* t */, 
          ARGS... args) { 
    f(args...); 
    } 
}; 

template < typename... ARGS > 
void applyTuple(std::function<void(ARGS...)>& f, 
       std::tuple<ARGS...> const& t) { 
    apply_func<sizeof...(ARGS), ARGS...>::applyTuple(f, t); 
} 

template<typename... ARGS> 
class Foo 
{ 
    std::function<void(ARGS...)> m_f; 
    std::tuple<ARGS...> *argument_pack; 

    public: 
    Foo(std::function<void(ARGS...)> f):m_f(f){} 
    void operator()(ARGS... args); 
    void run(); 

}; 

template<typename... ARGS> 
void Foo<ARGS...>::operator()(ARGS... args) 
{ 
    m_f(args...); // this works 
} 

template<typename... ARGS> 
void Foo<ARGS...>::run() 
{ 
    applyTuple<ARGS...>(m_f, *argument_pack); // this doesn't compile 
} 

void bar(int i, double d){} 

int main(void) 
{ 
    Foo<int,double> foo(bar); 
    foo(1,1.0); // this works 
    foo.run(); // this doesn't compile 
} 

あなたがしてコンパイルする場合は、次の回答に基づいて、

そして、このコードを思い付い'g ++ -std = C++ 0x '最後の行の次にこのエラーが表示されます:

test.cc: In function ‘void applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&) [with ARGS = {int, double}]’: 
test.cc:52:9: instantiated from ‘void Foo<ARGS>::run() [with ARGS = {int, double}]’ 
test.cc:61:17: instantiated from here 
test.cc:27:8: error: no matching function for call to ‘apply_func<2, int, double>::applyTuple(std::function<void(int, double)>&, const std::tuple<int, double>&)’ 
test.cc:27:8: note: candidate is: 
test.cc:6:19: note: static void apply_func<N, ARGS>::applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&, ARGS ...) [with int N = 2, ARGS = {int, double}] 
test.cc:6:19: note: candidate expects 4 arguments, 2 provided 
test.cc: In static member function ‘static void apply_func<N, ARGS>::applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&, ARGS ...) [with int N = 2, ARGS = {int, double}]’: 
test.cc:27:8: instantiated from ‘void applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&) [with ARGS = {int, double}]’ 
test.cc:52:9: instantiated from ‘void Foo<ARGS>::run() [with ARGS = {int, double}]’ 
test.cc:61:17: instantiated from here 
test.cc:9:9: error: no matching function for call to ‘apply_func<1>::applyTuple(std::function<void(int, double)>&, const std::tuple<int, double>&, const double&, int&, double&)’ 
test.cc:9:9: note: candidate is: 
test.cc:6:19: note: static void apply_func<N, ARGS>::applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&, ARGS ...) [with int N = 1, ARGS = {}] 
test.cc:6:19: note: candidate expects 2 arguments, 5 provided 
test.cc: In static member function ‘static void apply_func<N, ARGS>::applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&, ARGS ...) [with int N = 1, ARGS = {}]’: 
test.cc:9:9: instantiated from ‘static void apply_func<N, ARGS>::applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&, ARGS ...) [with int N = 2, ARGS = {int, double}]’ 
test.cc:27:8: instantiated from ‘void applyTuple(std::function<void(ARGS ...)>&, const std::tuple<_Elements ...>&) [with ARGS = {int, double}]’ 
test.cc:52:9: instantiated from ‘void Foo<ARGS>::run() [with ARGS = {int, double}]’ 
test.cc:61:17: instantiated from here 
test.cc:9:9: error: no matching function for call to ‘get(const std::tuple<>&)’ 
test.cc:9:9: note: candidates are: 
/usr/include/c++/4.6/utility:133:5: note: template<long unsigned int _Int, class _Tp1, class _Tp2> typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(std::pair<_Tp1, _Tp2>&) 
/usr/include/c++/4.6/utility:138:5: note: template<long unsigned int _Int, class _Tp1, class _Tp2> const typename std::tuple_element<_Int, std::pair<_Tp1, _Tp2> >::type& std::get(const std::pair<_Tp1, _Tp2>&) 
/usr/include/c++/4.6/tuple:531:5: note: template<long unsigned int __i, class ... _Elements> typename std::__add_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(std::tuple<_Elements ...>&) 
/usr/include/c++/4.6/tuple:538:5: note: template<long unsigned int __i, class ... _Elements> typename std::__add_c_ref<typename std::tuple_element<__i, std::tuple<_Elements ...> >::type>::type std::get(const std::tuple<_Elements ...>&) 

私は何が欠けていますか?ありがとう! 、あなたはタプルへのポインタを渡しているargument_packであるため、runの内、

template < typename... ARGS > 
void applyTuple(std::function<void(ARGS...)>& f, 
       std::tuple<ARGS...> const& t) { 
    apply_func<sizeof...(ARGS), ARGS...>::applyTuple(f, t); 
} 

しかし:

答えて

0

私はそれを解決しました。ポインタエラーは、ユーザーが指摘

  1. How do I expand a tuple into variadic template function's arguments?
  2. templatetypedef私は戻って、この記事でタプルを適用する元のバージョンに行かなければならなかったことは、3つのエラーの組み合わせでした。タプル、関数、クラスはすべて同じため、すべてのテンプレートパラメータをARGS...に変更しました。正直言って、私はまだそれがうまくいかない理由を理解していません...
  3. 私はしたようにstd::function<void(ARGS...)>オブジェクトの代わりに関数ポインタを(void (*m_f) (ARGS...);)として保存しなければなりませんでした。それに応じてコンストラクターを変更する必要がありました。

ありがとうございました!

+0

あなたの答えを編集して、あなたの実際の解決策を含めることができますか? –

2

私はこの問題は、applyTupleはその2番目のパラメータとしてタプルへの参照を取ることだと思いますタプルへのポインタ:

std::tuple<ARGS...> *argument_pack; 

あなたは

applyTuple<ARGS...>(m_f, *argument_pack); 
0であることを runの体を変更した場合

あなたの問題は解決しないと思います。

希望すると便利です。

+0

うわー、これは恥ずかしいです...私はvariadicテンプレートの周りに投げていると私は私が必要とするポインタを逆参照することができません!とにかく、それはまだコンパイルされていません。エラーを指摘していただきありがとうございます!私は質問を更新しました。 – steffen

+0

小さなディテールを省略すると、複雑なテンプレート混乱ではなく、何をしたのかをコンパイラから伝えてくれる、きれいで分かりやすいエラーメッセージが表示される限り、 – CashCow

0

apply_func<N-1>::...とは言えません。これにより、ARGS = {}の構造体がインスタンス化されます。したがって、「候補は2つの引数、5つの引数が必要です」というエラーが発生します。

また、applyTupleに、あなたは4つのパラメータ受け入れることを期待する、apply_func<sizeof...(ARGS), ARGS...>::applyTupleを使用している:機能f、タプルt、およびARGS... argsをしていますが、引数を渡すことはできません。したがって、「候補は4つの引数を期待し、 2提供 "エラー。

代替ソリューションとして、あなたは私のvtmpライブラリを使用して

template<typename... ARGS> 
void Foo<ARGS...>::run() 
{ 
    utils::tuple_apply(*argument_pack, m_f); 
} 

を使用することができますが(注:G ++ 4.7が必要です)

関連する問題