I propose another solution, really different from the code in the question, that I think is a lot more efficient (creation on only one std::array
; blender obtained by template index sequence)
#include <array>
#include <utility>
#include <iostream>
template <typename T, std::size_t I0>
int blenderH (double t, T const & arr, std::index_sequence<I0> const &)
{ return arr[I0]; }
template <typename T, std::size_t I0, std::size_t ... Is>
auto blenderH (double t, T const & arr,
std::index_sequence<I0, Is...> const &)
-> std::enable_if_t<0U != sizeof...(Is), int>
{ return (1-t) * blenderH(t, arr, std::index_sequence<(Is-1U)...>{})
+ t * blenderH(t, arr, std::index_sequence<Is...>{}); }
template <typename ... Args>
int blender (double t, Args ... as)
{
static constexpr auto size = sizeof...(Args);
return blenderH(t, std::array<int, size>{ { as... } },
std::make_index_sequence<size>{});
}
int main()
{ std::cout << blender(.3, 23, 42, 89) << std::endl; }
Unfortunately also this solution works (std::index_sequence
and std::make_index_sequence
) starting from C++14.
-- EDIT --
Caleth say.
Some explanation of what is going on here would help. I am confused by the lack of I0
in the body of the second overload.
I try an explanation.
Suppose is called the recursive version of BlenderH()
(the second overload) with a list of index in the std::index_sequence
value. Say 5, 6, 7 and 8; so I0
is 5
and Is...
is 6, 7, 8
.
We have to recursive call blenderH()
with indexes 5, 6, 7
first and with 6, 7, 8
next.
We can avoid to use I0
(5
) because
5, 6, 7
is obtained from 6, 7, 8
reducing by 1 every value (so the std::index_sequence<(Is-1U)...>
for the first recursive call)
and 6, 7, 8
is Is...
without modifications (so the std::index_sequence<Is...>
in the second one.
From the practical point of view, I0
is declared only to be discarded; ther is no need to use it.