2017-05-06 26 views
0

我嘗試傳遞給variadic模板函數一個引用列表並將它傳遞給另一個函數。我寫的代碼如下:將引用傳遞給variadic-templates使用std :: reference-wrapper

template <typename T> 
void fun(cv::Point_<T> & pt) { pt.x++; pt.y++; } 

template <class ... args> 
void caller(args & ... list) { 

    typedef typename std::tuple_element<0, std::tuple<args...> >::type T; 

    std::array<std::reference_wrapper<T>, sizeof...(list)> values {list ...  }; 

    for(int i=0; i<values.size(); i++) 
     fun(values[i]); 

} 

然後我把這樣的函數調用:

cv::Point2f a, b, c; 

caller(a, b, c); 

編譯器給我下面的錯誤:

No matching function for call to 'fun' 
Candidate template ignored: could not match 'Point_' against 'reference_wrapper' 

我失蹤?

+2

你想做什麼?引用包裝只是多餘的。你是否真的試圖爲每個參數調用'fun'? –

+0

或多或少是的。然而,我的問題中的代碼是對真實代碼的簡化。 – thewoz

回答

2

儘管std::reference_wrapper<T>已隱式轉換爲T&,但您不能同時使用隱式轉換和模板參數推演,並且需要模板參數推導以調用fun

嘗試

fun(values[i].get()); 
1

由於這個目標可能是遍歷所有args,這裏有一個更通用的解決方案。我們要實現for_pack

template<typename... Args, typename F> 
void for_pack(F function, Args&&... args) { 
    using expand = int[]; 
    (void)expand{(function(std::forward<Args>(args)), void(), 0)..., 0}; 
} 

這將在Args執行function每一個args

現在,你的函數caller是更容易實現:

template <typename... args> 
void caller(args&... list) { 
    for_pack([&](cv::Point_<T>& arg){ 
     fun(arg); 
    }, list...); 
} 
+0

@Walter對不起,現在已更正。 –

+0

你不需要那個void(),也不需要所有的'expand'東西,看看我的答案。 – Walter

+0

@Walter是的,你需要'void()'。如果'函數'碰巧返回一個重載'operator(int)'的對象,它可能導致令人討厭的編譯錯誤。順便說一句,你的解決方案應該觸發'tmp'不被使用的警告。 –

2

更簡單的是

template <typename...Args> 
void caller(Args&...args) 
{ 
    auto tmp = { (func(args),0)..., 0 }; 
} 

此使用該參數包擴能支撐體系初始化列表中發生的事實。由於func()返回void,我們不能簡單地使用{ func(args)... },但使用(func(args),0)有一個int。最後,最後的0是爲了確保代碼在空參數包的情況下編譯(並且不執行任何操作)。

可以概括這一點,並寫了一包的每個元素調用一個給定的泛型函數模板:

template <typename Func, typename...Args> 
void call_for_each(Func &&func, Args&&...args) 
{ 
    auto unused = { (func(std::forward<Args>(args)),0)...,0 }; 
} 

這可能是這樣的(C++ 14)

int main() 
{ 
    int a=1; 
    double b=2.4; 
    auto func = [](auto&x) { std::cout<<' '<<x++; }; 
    call_for_each(func,a,b); 
    std::cout<<'\n'; 
    call_for_each(func,a,b); 
    std::cout<<'\n'; 
} 
使用

這使用C++ 14 lambda(參數爲auto)。請注意,參數數據包必須在call_for_each的模板參數中排在最後。

+0

確實有效。然而,這對我來說就像亞拉米奇。但是什麼不是無效的,我需要總結返回的值? – thewoz

+0

這是另一個(好的)問題。發表它。 – Walter

+0

@Walter看起來'call_for_each'不能接受可變lambda。你介意用'Func func'或者'Func && func'來替換'Func const&func'?謝謝。 –