传入std::array作为模板可变函数的参数
Passing std::array as arguments of template variadic function
我正在尝试学习c++ 11中的可变模板。我有一个类,它基本上是std::array
的包装器。我希望能够将函数对象(理想情况下是lambdas)传递给成员函数,然后将std::array
的元素作为函数对象的参数传递。
我使用static_assert
来检查参数的数量是否与数组的长度相匹配,但我无法想到将元素作为参数传递的方法。
代码
#include <iostream>
#include <array>
#include <memory>
#include <initializer_list>
using namespace std;
template<int N, typename T>
struct Container {
template<typename... Ts>
Container(Ts&&... vs) : data{{std::forward<Ts>(vs)...}} {
static_assert(sizeof...(Ts)==N,"Not enough args supplied!");
}
template< typename... Ts>
void doOperation( std::function<void(Ts...)>&& func )
{
static_assert(sizeof...(Ts)==N,"Size of variadic template args does not match array length");
// how can one call func with the entries
// of data as the parameters (in a way generic with N)
}
std::array<T,N> data;
};
int main(void)
{
Container<3,int> cont(1,2,3);
double sum = 0.0;
auto func = [&sum](int x, int y, int z)->void{
sum += x;
sum += y;
sum += z;
};
cont.doOperation(std::function<void(int,int,int)>(func));
cout << sum << endl;
return 0;
}
所以我的问题(如代码中所示)是如何将data
的条目以与N
通用的方式传递到函数func
上?
附加问题:是否有可能消除在main中不美观的转换为std::function
并直接传递lambda ?
考虑到众所周知的索引基础设施:
namespace detail
{
template<int... Is>
struct seq { };
template<int N, int... Is>
struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };
template<int... Is>
struct gen_seq<0, Is...> : seq<Is...> { };
}
你可以这样重新定义你的类模板:
template<int N, typename T>
struct Container {
template<typename... Ts>
Container(Ts&&... vs) : data{{std::forward<Ts>(vs)...}} {
static_assert(sizeof...(Ts)==N,"Not enough args supplied!");
}
template<typename F>
void doOperation(F&& func)
{
doOperation(std::forward<F>(func), detail::gen_seq<N>());
}
template<typename F, int... Is>
void doOperation(F&& func, detail::seq<Is...>)
{
(std::forward<F>(func))(data[Is]...);
}
std::array<T,N> data;
};
下面是一个的实例。
注意,您不需要在main()
中构造std::function
对象:std::function
可以从lambda隐式构造。但是,在这里甚至不需要使用std::function
,这可能会导致不必要的运行时开销。
在上面的解决方案中,我只是让可调用对象的类型是一个可以由编译器推断的模板参数
您可以使用此实用工具模板在编译时创建索引序列:
template< std::size_t... Ns >
struct indices {
typedef indices< Ns..., sizeof...( Ns ) > next;
};
template< std::size_t N >
struct make_indices {
typedef typename make_indices< N - 1 >::type::next type;
};
template<>
struct make_indices< 0 > {
typedef indices<> type;
};
然后创建一个调用函数,将indices
作为参数,这样您就可以推导出索引序列:
template<typename... Ts, size_t...Is>
void call(std::function<void(Ts...)>&& func, indices<Is...>)
{
func( data[Is]... );
}
然后你可以这样称呼它:
template< typename... Ts>
void doOperation( std::function<void(Ts...)>&& func )
{
static_assert(sizeof...(Ts)==N,"Size of variadic template args does not match array length");
call( std::forward<std::function<void(Ts...)>>(func), typename make_indices<N>::type() );
}
相关文章:
- static_assert在宏中,但也可以扩展到可以用作函数参数的东西
- C++中的高效循环缓冲区,它将被传递给C样式数组函数参数
- 当从函数参数中的临时值调用复制构造函数时
- 如何从"decltype()"获取函数参数的数量<funtion>?
- 如何将lambda作为模板类的成员函数参数
- 模板参数推导失败,函数参数/参数不匹配
- 如何在C++中将迭代器作为函数参数传递
- 将函数参数"const char*"转换为"std::string_view"是
- C++ 如何将数组值解压缩为函数参数
- 主函数参数的属性
- 具有两个间接寻址运算符 (C++) 的函数参数的用途
- "Warning: Comma within array index expression"但逗号分隔函数参数
- 如何定义在用作函数参数时工作的类模板的转换
- 将函数参数完美转发到函数指针:按值传递呢?
- 为什么我不能将引用作为 std::async 的函数参数传递
- 什么..(省略号)作为函数原型中唯一的函数参数,C++?
- 是否可以就地构造一个固定大小的数组作为函数参数?
- 接受模板作为函数参数
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- Arduino 函数参数