patterncppModerate
Improved indices trick
Viewed 0 times
indicestrickimproved
Problem
We all know about the indices trick, right? Here's (hopefully) an improved version...
Usage:
Any suggestions?
template struct indices { };
namespace detail
{
template struct catenate_indices;
template
struct catenate_indices, indices >
{
using indices_type = indices;
};
template struct expand_indices;
template
struct expand_indices::type>
{
using indices_type = indices;
};
template
struct expand_indices::type>
{
static_assert(A B");
using indices_type = typename catenate_indices::indices_type,
typename expand_indices::indices_type
>::indices_type;
};
}
template
struct make_indices : detail::expand_indices::indices_type
{
};
template
struct make_indices_range : detail::expand_indices::indices_type
{
};Usage:
#include
#include "utility.hpp"
template
void show_indices(indices)
{
[](...){}((((::std::cout ());
return 0;
}Any suggestions?
Solution
You can get rid of the `
header by replacing your std::enable_if by a bool template specialization:
template
struct expand_indices_impl;
template
struct expand_indices:
expand_indices_impl
{};
template
struct expand_indices_impl
{
using indices_type = indices;
};
template
struct expand_indices_impl
{
static_assert(A B");
using indices_type = typename catenate_indices::indices_type,
typename expand_indices::indices_type
>::indices_type;
};
Moreover, in C++ (and many other programming languages, see Python range for example), ranges tend to have the end-exclusive form [begin, end); therefore, make_indices_range should contain the indices from 3 to 8, and not from 3 to 9. It is easy to alter the behaviour:
template
struct make_indices:
detail::expand_indices::indices_type
{};
template
struct make_indices_range:
detail::expand_indices::indices_type
{};
As proposed in the comments, make_indices_range also needs to provide an empty range when A == B`:template
struct make_indices_range:
indices<>
{};Code Snippets
template <::std::size_t, ::std::size_t, bool>
struct expand_indices_impl;
template <::std::size_t A, ::std::size_t B>
struct expand_indices:
expand_indices_impl<A, B, A==B>
{};
template <::std::size_t A, ::std::size_t B>
struct expand_indices_impl<A, B, true>
{
using indices_type = indices<A>;
};
template <::std::size_t A, ::std::size_t B>
struct expand_indices_impl<A, B, false>
{
static_assert(A < B, "A > B");
using indices_type = typename catenate_indices<
typename expand_indices<A, (A + B) / 2>::indices_type,
typename expand_indices<(A + B) / 2 + 1, B>::indices_type
>::indices_type;
};template <::std::size_t A>
struct make_indices:
detail::expand_indices<0, A-1>::indices_type
{};
template <::std::size_t A, ::std::size_t B>
struct make_indices_range:
detail::expand_indices<A, B-1>::indices_type
{};template <::std::size_t A>
struct make_indices_range<A, A>:
indices<>
{};Context
StackExchange Code Review Q#39648, answer score: 11
Revisions (0)
No revisions yet.