Split the parameter packet into 0 ... N-1 and Nth element

I would like to split the parameter package into the first parameters N - 1 and Nth without using the typical index_sequence and tuple tags, but it seems that I cannot wrap it around it, but I'm sure this should be feasible? (getting the last element is quite simple with recursion).

The last call function looks like

void Fun( Foo a, Bar b ); 

and a is acquired from the variational in turn:

 template< class... T > Foo CalcFoo( T... args ); 

My current implementation:

 //get the last item of the pack template< class T > T split_last( T t ){ return t; } template< class... T > T split_last( T, T... t ){ return split_last( t... ); } //helper template< class... T, size_t... Indices > Foo CalcFoo( const std::tuple< T... >& args, index_sequence< Indices... > ) { return CalcFoo( std::get< Indices >( args )... ); } //split and call template< class... T > void MoreFun( T... args ) { //make a tuple containing all, then get n -1 items out of it const auto tup = std::make_tuple< T... >( args... ); Fun( CalcFoo( tup, make_index_sequence< sizeof...( T ) - 1 >() ), split_last( args... ) ); } 

update , not wanting to know how to do this without a tuple just for the sake of it, I also asked about it, because for some reason I thought that a tuple could cause overhead. This ignores the premature optimization mantra, which, as usual, turned out to be correct again. Compiled in release mode with VS2013, both mine and Horstling code give the same assembler code. Everyone, including CalcFoo , builds up to the Fun call. In other words: the tuple has completely disappeared. Therefore, I will probably stick to this implementation because it is pretty clear.

+5
source share
1 answer

Well, let it be creative. I am sure there is a more โ€œstandardโ€ way to do this, but I kind of like this solution;)

http://coliru.stacked-crooked.com/a/25a3fa276e56cd94

The basic idea is to rotate the arguments recursively until we can separate the last argument (earlier).

 template <size_t N> struct MoreFunHelper { template <class Head, class... Tail> static void RotateLeft(Head head, Tail... tail) { MoreFunHelper<N - 1>::RotateLeft(tail..., head); } }; template <> struct MoreFunHelper<0> { template <class Head, class... Tail> static void RotateLeft(Head head, Tail... tail) { Fun(CalcFoo(tail...), head); } }; template< class... T > void MoreFun(T... args) { MoreFunHelper<sizeof...(T) - 1>::RotateLeft(args...); } 

So, if we start with the arguments

 1 2 3 4 5 

he rotates them 4 times:

 2 3 4 5 1 3 4 5 1 2 4 5 1 2 3 5 1 2 3 4 

Now we can divide them smoothly into [5] and [1 2 3 4], which is what we want. At this point, recursion stops and simply calls the CalcFoo and Fun functions.

+4
source

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


All Articles