Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Indices trick used for several components

Consider this fully working code:

#include <type_traits>

template <typename T, typename IndexPack> struct Make;

template <typename T, template <T...> class P, T... Indices>
struct Make<T, P<Indices...>> {
    using type = P<(Indices+1)..., (-3*Indices)..., (Indices-1)...>;
};

template <int...> class Pack;

int main() {
    static_assert (std::is_same<Make<int, Pack<1,2,3,4>>::type, 
        Pack<2,3,4,5, -3,-6,-9,-12, 0,1,2,3>>::value, "false");
}

What I actually want the output to be is

Pack<2,-3,0, 3,-6,1, 4,-9,2, 5,-12,3>

instead of Pack<2,3,4,5, -3,-6,-9,-12, 0,1,2,3>. I first tried

using type = P<(Indices+1, -3*Indices, Indices-1)...>;

but that is simply understood by the compiler to be a useless comma operator. What is the desired syntax to get what I want? If there is no such syntax, what is the cleanest way to do this, keeping in mind that using Indices 3 times is just an example (we may want to use it more than 3 times). Please don't tell me that I have to write a helper to extract the individual packs and then "interlace" all the elements. That nightmarish method cannot be the best solution (and such a solution would also only work if we knew exactly how many individual packs to extract).

Would defining

template <typename T, template <T...> class P, T I>
struct Component {
    using type = P<I+1, -3*I, I-1>;
};

help somehow? Make a pack expansion on this?

like image 442
prestokeys Avatar asked Sep 28 '22 03:09

prestokeys


1 Answers

Yes, you can concat recursively:

template <typename, typename, typename> struct Concat;

template <typename T, template <T...> class P, T... A, T... B>
struct Concat<T, P<A...>, P<B...>> {
    using type = P<A..., B...>;
};

template <typename T, typename IndexPack> struct Make;

template <typename T, template <T...> class P, T... I, T F >
struct Make<T, P<F, I...>> {
    using type = typename Concat<T,
                                 typename Make<T, P<F>>::type,
                                 typename Make<T, P<I...>>::type>::type;
};

template <typename T, template <T...> class P, T I>
struct Make<T, P<I>> {
    using type = P<I+1, -3*I, I-1>;
};

Demo

like image 135
Columbo Avatar answered Oct 06 '22 02:10

Columbo