固定大小的容器到可变参数模板参数列表转换

时间:2016-02-05 19:32:42

标签: c++ c++11 variadic-templates

我必须调用可变参数模板函数,它可以使用任意数量的参数。

template < class ... Args >
void f( Args&... args);

我希望编写一个小的包装函数,以便我可以使用固定大小容器(如std :: array)中包含的N个相同类型的参数调用f

目标是编写类似

的内容
std::array<int, 3> arr = {1,2,3};
wrapper(arr); // calls f(1,2,3);

我尝试使用初始化列表和std::forward的某些组合,但无济于事。有没有办法达到我想要的目的?

2 个答案:

答案 0 :(得分:7)

如果您的编译器支持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());
}

Live Demo

对于基于此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>());
}

Live Demo

答案 1 :(得分:2)

我设法使用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);

Live version here