So someone asked a question then deleted it, but I found it an interesting challenge.
They had this weird type, and had run into the problem that Concat and Range were castable to Sequences but were not Sequences (for obvious reasons)
template<unsigned... Is> struct Sequence{};
template<typename... Is> struct Concat{};
template<unsigned... Is> struct Concat<Sequence<Is...>> : public Sequence<Is...> {};
template<unsigned... Is, unsigned... Js, typename... Rest>
struct Concat<Sequence<Is...>, Sequence<Js...>, Rest...>
: Concat<Sequence<Is..., Js...>, Rest...> {};
So I figured it'd be an interesting challenge to do this right, making everything the same type.
So my first pass at Concat ran into unexpected problems...How on earth does one extract the template parameters for the Sequences? I ended up using a function below:
template <unsigned... Is,unsigned... Js>
constexpr auto concat_results(Sequence<Is...>,Sequence<Js...>) -> Sequence<Is...,Js...>
{
return Sequence<Is...,Js...>();
}
template <typename seq1,typename seq2>
using Concat = decltype(concat_results(seq1(),seq2()));
Bizarrely, I think that's the shortest way to declare it, though it is a little weird. However, the concat_results could be useful (on references of the sequences) and the type can be useful in other places. Anyone have a better way to do that?
Next up was range, which I did with a recursive struct helper:
template <unsigned N>
struct nrange_helper
{
using Range = Concat<typename nrange_helper<N-1>::Range,Sequence<N>>;
};
template <>
struct nrange_helper<0>
{
using Range = Sequence<0>;
};
template <unsigned N>
using Range = typename nrange_helper<N>::Range;
Again, its weird, but it works...but I feel like there should be a better way. Anyone got one?