将引用传递给variadic-templates使用std :: reference-wrapper

将引用传递给variadic-templates使用std :: reference-wrapper

问题描述:

我尝试传递给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

尽管std::reference_wrapper<T>已隐式转换为T&,但您不能同时使用隐式转换和模板参数推演,并且需要模板参数推导以调用fun

尝试

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

由于这个目标可能是遍历所有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'不被使用的警告。 –

更简单的是

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'?谢谢。 –