Reputation: 2684
So, C++14 provides struct make_index_sequence<N>
for generating an index sequence from 0
to N-1
. I am wondering how to implement one to generate an index sequence in a given range. For example:
template <size_t Min, size_t Max>
struct make_index_range;
// make_index_range<5, 9> will give index_sequence<5, 6, 7, 8>
Upvotes: 4
Views: 1469
Reputation: 673
The answer, which uses C++20, given by @edrezen can be written more briefly
#include <utility>
#include <iostream>
template<typename T, T Min, T Max>
constexpr auto make_integer_range ()
{
static_assert (Max>=Min);
return [] <T... Is> (std::integer_sequence<T,Is...>)
{
return std::integer_sequence<T, Is+Min...>{};
}(std::make_integer_sequence<T, Max-Min+1>{});
}
// integer sequence of -1,0,1,2,3
constexpr auto myrange = make_integer_range<int,-1,3> ();
// debugging aid (https://en.cppreference.com/w/cpp/utility/integer_sequence)
template<typename T, T... ints>
void print_sequence(std::integer_sequence<T, ints...> int_seq)
{
std::cout << "The sequence of size " << int_seq.size() << ": ";
((std::cout << ints << ' '), ...);
std::cout << '\n';
}
int main() {
print_sequence(myrange);
}
Upvotes: 0
Reputation: 1628
I know that the question is tagged with c++14 but it may be interesting to have a version for newer versions of the standard where metaprogramming is a little bit easier (not so obvious in this example though).
Moreover, I also needed to have a range of integers not necessarely bigger than 0, so the following code (for c++20):
#include <numeric>
#include <array>
template<typename T, T Min, T Max>
constexpr auto make_integer_range ()
{
static_assert (Max>=Min);
// we create an array filled with the integers from the given [Min,Max] bounds.
constexpr auto arr = []
{
std::array<T, Max-Min+1> a;
std::iota (a.begin(), a.end(), Min);
return a;
} ();
// we create the integer sequence from the content of the array
auto build = [&arr] <std::size_t... Is> (std::index_sequence<Is...>)
{
return std::integer_sequence<T, arr[Is]...>{};
};
return build (std::make_index_sequence<arr.size()>{});
}
// integer sequence of -1,0,1,2,3
constexpr auto myrange = make_integer_range<int,-1,3> ();
int main() {}
Upvotes: 0
Reputation: 171303
The way you defined index_range
(before the question was edited) the answer is simply:
template<std::size_t Min, std::size_t Max>
using make_index_range = index_range<Min, Max>;
Which is not very useful.
So I'm going to assume you mean make_index_range<5, 9>
will give index_sequence<5, 6, 7, 8>
, which can be done like this:
#include <utility>
template<std::size_t N, std::size_t... Seq>
constexpr std::index_sequence<N + Seq ...>
add(std::index_sequence<Seq...>)
{ return {}; }
template<std::size_t Min, std::size_t Max>
using make_index_range = decltype(add<Min>(make_index_sequence<Max-Min>()));
Or if you want make_index_range
to be a class template, define add
as above and then:
template<std::size_t Min, std::size_t Max>
struct make_index_range {
using type = decltype(add<Min>(make_index_sequence<Max-Min>()));
};
(But with this you have to use make_index_range<5, 9>::type
so the alias template is probably better, and closer to how make_index_sequence
works.)
Upvotes: 12