固定大小的容器到可变参数模板参数列表的转换
fixed size container to variadic template argument list conversion
我必须调用一个可变参数模板函数,它可以接受任意数量的参数。
template < class ... Args >
void f( Args&... args);
我想写一个小包装函数,这样我就可以调用 f
并在 std::array.
等固定大小的容器中包含 N 个相同类型的参数
目标是写类似
的东西
std::array<int, 3> arr = {1,2,3};
wrapper(arr); // calls f(1,2,3);
我尝试使用初始化列表和 std::forward
的某种组合,但无济于事。有没有办法实现我想要的?
如果您的编译器支持 C++14,您可以按以下方式进行:
template <class ... Args>
void f(Args&&... args) {
...
}
template<typename T, std::size_t N, std::size_t... I>
void wrapper_impl(std::array<T, N> const &arr, std::index_sequence<I...>) {
f(arr[I]...);
}
template<typename T, std::size_t N,
typename Indices = std::make_index_sequence<N>>
void wrapper(std::array<T, N> const &arr) {
wrapper_impl(arr, Indices());
}
对于基于此 SO answer 的 C++11,您可以编写一些额外的机制并按如下方式执行(尽管尚未测试):
namespace detail {
template<std::size_t... Is> struct seq {};
template<std::size_t N, int... Is> struct gen_seq : gen_seq<N-1,N-1, Is...> {};
template<std::size_t... Is> struct gen_seq<0, Is...> : seq<Is...> {};
}
template <class ... Args>
void f(Args&&... args) {
...
}
template<typename T, std::size_t N, std::size_t... I>
void wrapper_impl(std::array<T, N> const &arr, detail::seq<I...>) {
f(arr[I]...);
}
template<typename T, std::size_t N>
void wrapper(std::array<T, N> const &arr) {
wrapper_impl(arr, detail::gen_seq<N>());
}
我设法使用 std::array
解决了它,灵感来自 How do I expand a tuple into variadic template function's arguments?
中的元组解决方案
(编辑:std::array 版本,第一个版本使用原始指针)
// Function I want to call :
template< class... Args >
void f( Args&... args ) {
// ...
}
使用从数组末尾获取参数的递归模板(以便它们以正确的顺序结束)。
I = 0
处的特化具有 Args..args
中的所有参数并调用 f()
namespace Helper {
template< unsigned int N, unsigned int I >
struct Caller {
template< class T, class...Args >
static void call( const std::array<T,N>& arr, Args&... args ){
Caller<N,I-1>::call( arr, std::get<I-1>(arr), args... );
}
};
template < unsigned int N >
struct Caller<N, 0> {
template< class T, class...Args >
static void call( const std::array<T,N>& arr, Args&... args ) {
f(args...);
}
};
}
让我们用一个漂亮的函数来包装它
template< typename T, unsigned N >
void call_f( const std::array<T,N>& arr ){
Helper::Caller<N,N>::call(arr);
}
调用代码如下所示。
std::array<float,3> array = {4.3, 3.14,2.1} ;
call_f(array);
我必须调用一个可变参数模板函数,它可以接受任意数量的参数。
template < class ... Args >
void f( Args&... args);
我想写一个小包装函数,这样我就可以调用 f
并在 std::array.
目标是写类似
的东西std::array<int, 3> arr = {1,2,3};
wrapper(arr); // calls f(1,2,3);
我尝试使用初始化列表和 std::forward
的某种组合,但无济于事。有没有办法实现我想要的?
如果您的编译器支持 C++14,您可以按以下方式进行:
template <class ... Args>
void f(Args&&... args) {
...
}
template<typename T, std::size_t N, std::size_t... I>
void wrapper_impl(std::array<T, N> const &arr, std::index_sequence<I...>) {
f(arr[I]...);
}
template<typename T, std::size_t N,
typename Indices = std::make_index_sequence<N>>
void wrapper(std::array<T, N> const &arr) {
wrapper_impl(arr, Indices());
}
对于基于此 SO answer 的 C++11,您可以编写一些额外的机制并按如下方式执行(尽管尚未测试):
namespace detail {
template<std::size_t... Is> struct seq {};
template<std::size_t N, int... Is> struct gen_seq : gen_seq<N-1,N-1, Is...> {};
template<std::size_t... Is> struct gen_seq<0, Is...> : seq<Is...> {};
}
template <class ... Args>
void f(Args&&... args) {
...
}
template<typename T, std::size_t N, std::size_t... I>
void wrapper_impl(std::array<T, N> const &arr, detail::seq<I...>) {
f(arr[I]...);
}
template<typename T, std::size_t N>
void wrapper(std::array<T, N> const &arr) {
wrapper_impl(arr, detail::gen_seq<N>());
}
我设法使用 std::array
解决了它,灵感来自 How do I expand a tuple into variadic template function's arguments?
(编辑:std::array 版本,第一个版本使用原始指针)
// Function I want to call :
template< class... Args >
void f( Args&... args ) {
// ...
}
使用从数组末尾获取参数的递归模板(以便它们以正确的顺序结束)。
I = 0
处的特化具有 Args..args
中的所有参数并调用 f()
namespace Helper {
template< unsigned int N, unsigned int I >
struct Caller {
template< class T, class...Args >
static void call( const std::array<T,N>& arr, Args&... args ){
Caller<N,I-1>::call( arr, std::get<I-1>(arr), args... );
}
};
template < unsigned int N >
struct Caller<N, 0> {
template< class T, class...Args >
static void call( const std::array<T,N>& arr, Args&... args ) {
f(args...);
}
};
}
让我们用一个漂亮的函数来包装它
template< typename T, unsigned N >
void call_f( const std::array<T,N>& arr ){
Helper::Caller<N,N>::call(arr);
}
调用代码如下所示。
std::array<float,3> array = {4.3, 3.14,2.1} ;
call_f(array);