2016-02-05 59 views
4

我必须调用一个可以带任意数量参数的可变参数模板函数。固定大小的容器到可变参数模板参数列表转换

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

我希望写一个小包装函数,这样我可以调用f与包含在比如std ::阵列的固定大小的容器相同类型的N个参数。

的目标是写类似

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

我试图用初始化列表的一些组合和std::forward但无济于事。有没有办法实现我想要的?

+3

我想你可能会寻找一个['的std :: integer_sequence'(http://en.cppreference.com/w/cpp/utility/integer_sequence) – NathanOliver

+0

@NathanOliver - - 如果参数的类型可能是“int”以外的东西呢? – Louen

+1

我看到了使它具有通用性的两个问题:从容器中创建一个元组,并将元组解包到参数包中。后一部分[已经完成](http://stackoverflow.com/a/1547118/440558),这留下了我不幸不知道该怎么做的元组的创建。 –

回答

2

我设法解决它使用std::array,由元组解决方案的启发在How do I expand a tuple into variadic template function's arguments?

(编辑:性病::数组版本,使用的第一个版本的原始指针)

// 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

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

对于C++ 11在此基础上SO answer你可以编写一些额外的机器做如下(尚未虽然测试):

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

相关问题