Various template expansion options

I want to prepare a list of pairs of values ​​from a structure using variable templates.

#include <vector> struct foo { foo(int a, int b) : a(a), b(b) {} int a; int b; }; struct Msg { std::vector<int> valueArray; }; template<typename... Args> Msg func(Args... args) { Msg msg; msg.valueArray = { sizeof...(args), (args.a)..., (args.b)... }; return msg; } int main() { Msg msg = func(foo{1,2}, foo{3,4}, foo{5,6}); } 

Msg, which returns func, will have valueArray = [3, 1, 3, 5, 2, 4, 6] .

Is there any simple way to deploy variable parameters in such a way where valueArray will look like valueArray = [3, 1, 2, 3, 4, 5, 6] ?

+6
source share
2 answers

The following is not as universal as we would like, but perhaps this is enough for you:

 template<typename Arr, std::size_t... Is> Msg func2( const Arr& arr, std::index_sequence<Is...> ) { Msg msg; msg.valueArray = { sizeof...(Is) / 2, ( ( Is % 2 == 0 ) ? std::get< Is / 2 >( arr ).a : std::get< Is / 2 >( arr ).b )... }; return msg; } template<typename... Args> Msg func(Args... args) { return func2( std::forward_as_tuple( args... ), std::make_index_sequence< 2*sizeof...(Args) >() ); } 

Living example

+4
source

Using the capabilities of C ++ 14, you can get a general solution:

 struct Msg { std::vector<int> values; }; template <std::size_t... indices, typename Tuple, typename OutputIt> void copy(std::index_sequence<indices...>, Tuple&& t, OutputIt out) { (void)std::initializer_list<int> { (*out++ = std::get<indices>(std::forward<Tuple>(t)), 0)... }; } template <typename Tuple, typename OutputIt> void copy(Tuple&& t, OutputIt out) { copy(std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>{}>{}, std::forward<Tuple>(t), out); } template <typename... Args> Msg func(Args... args) { auto cat = std::tuple_cat(args...); Msg m{{sizeof...(args)}}; copy(cat, std::back_inserter(m.values)); return m; } // For demonstration: template <typename... T> auto foo(T&&... t) {return std::make_tuple(std::forward<T>(t)...);} 

The use is more flexible than before:

 Msg msg = func(foo(1,2,3), foo(4), foo(5,6,7)); 

Demo

You can define foo as a tuple (fixed size), for example. using foo = std::tuple<int, int>; , then your example above compiles without an auxiliary function (after setting curly braces, of course).

+3
source

Source: https://habr.com/ru/post/986874/


All Articles