2016-02-05 40 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