template<class T, std::size_t I, std::size_t...Offs, class Tup>
T create( std::index_sequence<Offs...>, Tup&& tup ) {
return T( std::get<I+Offs>(std::forward<Tup>(tup))... );
}
template <unsigned N>
struct Pixel {
float color[N];
template<class...Ts,
std::enable_if_t< sizeof...(Ts)==N, bool > = true
>
Pixel(Ts&&...ts):color{ std::forward<Ts>(ts)... } {};
};
template <unsigned N>
struct PixelContainer {
std::vector<Pixel<N>> container;
template<class T0, class...Ts,
std::enable_if_t<!std::is_same<std::decay_t<T0>, PixelContainer>{}, bool> =true
>
PixelContainer(T0&& t0, Ts&&...ts):
PixelContainer( std::make_index_sequence<(1+sizeof...(Ts))/N>{}, std::forward_as_tuple( std::forward<T0>(t0), std::forward<Ts>(ts)... ) )
{}
PixelContainer() = default;
private:
template<class...Ts, std::size_t...Is>
PixelContainer( std::index_sequence<Is...>, std::tuple<Ts&&...>&& ts ):
container{ create<Pixel<N>, Is*N>( std::make_index_sequence<N>{}, std::move(ts) )... }
{}
};
create
принимает тип, начальный индекс и последовательность индексов смещений. Затем требуется кортеж.
Затем он создает тип из (начальный индекс) + (каждое из смещений) и возвращает его.
Мы используем это в частном ctor PixelContainer
. Он имеет элемент последовательности индекса для каждого из пикселей, элементы которого находятся в tuple
.
Мы умножаем элемент индексной последовательности на N, количество элементов в индексной последовательности и передаем его для создания. Кроме того, мы передаем последовательность индексов 0, ..., N-1 для смещений и основной кортеж.
Затем мы распаковываем это в {}
вложенный ctor для container
.
Публичный ctor просто пересылает в приватный ctor с нужным пакетом индексов по одному на элемент (равным числу аргументов / N). В нем есть что-то, раздражающее SFINAE enable_if_t
, чтобы он не проглатывал вещи, которые должны идти в копию.
Живой пример .
Кроме того,
std::enable_if_t<0 == ((sizeof...(Ts)+1)%N), bool> =true
может быть полезным дополнением SFINAE для публичного ctor PixelContainer
.
Без этого мы просто округляем и отбрасываем «лишние» элементы, переданные в PixelContainer
. С его помощью мы получаем «не найден ctor», если у нас есть дополнительные элементы (т.е. не кратные N).