Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fixed size container to variadic template argument list conversion

I have to call a variadic template function which can take any number of arguments.

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

I wish to write a small wrapper function so that I can call f with N arguments of the same type contained in a fixed size container like std::array.

The goal is to write something like

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

I tried to use some combination of initializer lists and std::forward but to no avail. Is there a way to achieve what I want ?

like image 973
Louen Avatar asked Jan 06 '23 17:01

Louen


2 Answers

If your compiler supports C++14 you can do it the following way:

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

For C++11 based on this SO answer you could code some extra machinery and do it as below (haven't test it though):

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

like image 182
101010 Avatar answered Jan 23 '23 19:01

101010


I managed to solve it using std::array , inspired by the tuple solution in How do I expand a tuple into variadic template function's arguments?

(Edited : std::array version, first version used raw pointers)

// Function I want to call : 
template< class... Args >
void f( Args&... args ) {
    // ...
}

Using recursive templates who grab the arguments from the end of the array (so that they end up in the correct order). A specialization at I = 0 has all the arguments in the Args..args and calls 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...);
    }
};
}

Let's wrap it up in a nice function

template< typename T, unsigned N >
void call_f( const std::array<T,N>& arr ){
    Helper::Caller<N,N>::call(arr);
}

Here's what the calling code looks like.

std::array<float,3> array = {4.3, 3.14,2.1} ;
call_f(array);

Live version here

like image 21
Louen Avatar answered Jan 23 '23 18:01

Louen