2012-02-08 41 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' next next to last line will give this error:

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 ...>&) 

我錯過了什麼?謝謝!

回答

0

我解決它。這是三個錯誤的組合:

  1. 指針錯誤所指出的用戶:templatetypedef
  2. 我不得不回去後這一應用的元組的原始版本:How do I expand a tuple into variadic template function's arguments?。我將所有模板參數改爲ARGS...,因爲對於元組,函數和類他們都是一樣的。老實說,我仍然不明白爲什麼這不應該工作...
  3. 函數指針必須像這樣存儲(void (*m_f) (ARGS...);)而不是像我一樣存儲std::function<void(ARGS...)>對象。構造者必須相應地改變,當然

謝謝你的回答!

+0

你能編輯你的答案來包含你的工作解決方案嗎? – 2013-03-08 21:45:40

2

我認爲這個問題是applyTuple需要參考元組作爲其第二個參數:

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

但,run裏面,你傳遞一個指針元組,由於argument_pack是指針指向一個元組:

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

如果更改run身體要

applyTuple<ARGS...>(m_f, *argument_pack); 

然後我認爲你的問題應該消失。

希望這會有所幫助!

+0

哇,這是令人尷尬的......我正在拋棄可變模板,我無法在需要的地方解引用指針!無論如何,它仍然沒有編譯。感謝您指出錯誤!我更新了這個問題。 – steffen 2012-02-08 09:18:35

+0

只要當你省略一個小細節時,你會從編譯器得到一個很好的清晰簡明的錯誤信息,告訴你你做了什麼,而不是一些複雜的模板混亂。 – CashCow 2012-02-08 18:32:15

0

你不能說apply_func<N-1>::...。這將用ARGS = {}實例化結構,因此「候選人期待2個參數,5個提供」錯誤。

此外,在applyTuple,你已經使用apply_func<sizeof...(ARGS), ARGS...>::applyTuple,這預計將接受4個參數:功能f,元組tARGS... args,但你無法通過ARGS,因此「候選預計4個參數, 2提供了「錯誤。

作爲一個替代的解決方案,你可以用我的vtmp庫,並使用

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

(注:需要G ++ 4.7)

相關問題