将引用传递给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'
我失踪?
尽管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...);
}
@Walter对不起,现在已更正。 –
你不需要那个void(),也不需要所有的'expand'东西,看看我的答案。 – Walter
@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
的模板参数中排在最后。
你想做什么?引用包装只是多余的。你是否真的试图为每个参数调用'fun'? –
或多或少是的。然而,我的问题中的代码是对真实代码的简化。 – thewoz