Daniel Wehner
Daniel Wehner

Reputation: 2189

Template specialization with condition

We are writing a generic implementation for range which uses recursive templates

template<typename T, std::size_t n>
class range<T,n> {
  // actual implementation
};
// Specialication for n = 0

The actual implementation can be found on https://github.com/jyujin/libefgy/blob/master/include/ef.gy/range.h

This works great so far, though you get into problems if you range exceeds 256 elements, as you have a template recursion with a limit.

In order to prevent this the idea was to specialize everything above a certain amount, like a size n over 255.

How can you write some condition, probably using enable_if?

Upvotes: 1

Views: 186

Answers (1)

Jarod42
Jarod42

Reputation: 217265

A possible solution/work around is to instantiate the given template as

template class range<int, 255>;

So now, your will have a new limit for n which will be 255 + recursiveLimit.
You have to specialize also the type T :-/

EDIT Now we have the OP's code :)

As I understand, your recursion is to create a sequence {0, 1, 2, .., N - 1}
The linear way to do this will hit recursion limit as soon N == limit.

The following will use divide and conquer to do the job:
So you should hit the limit when N ~= 2 ** limit

template <int ... Is> struct index_sequence {};

// Helper to concatenate several sequences
template<typename ... Ts> struct concat_seq;

template<int ... Is, int ...Is2, typename ... Ts>
struct concat_seq<index_sequence<Is...>, index_sequence<Is2...>, Ts...>
{
    typedef typename concat_seq<index_sequence<Is..., Is2...>, Ts...>::type type;
};

template<int ... Is>
struct concat_seq<index_sequence<Is...>>
{
    typedef index_sequence<Is...> type;
};

// Some test
static_assert(std::is_same<typename concat_seq<index_sequence<1>, index_sequence<2>, index_sequence<3>>::type, index_sequence<1, 2, 3>>::value, "");


// Helper to create the sequence
template <int N, int Offset = 0> struct make_seq;

template <int Offset> struct make_seq<0, Offset>
{
    typedef index_sequence<> type;
};

template <int Offset> struct make_seq<1, Offset>
{
    typedef index_sequence<Offset> type;
};

// Split the sequence to generate in two part (recursively)
template <int N, int Offset> struct make_seq
{
    typedef typename concat_seq<typename make_seq<N / 2, Offset>::type,
                                typename make_seq<N - N / 2, Offset + N / 2>::type>::type type;
};

// test
static_assert(std::is_same<typename make_seq<5>::type, index_sequence<0, 1, 2, 3, 4>>::value, "");
static_assert(std::is_same<typename make_seq<5, 2>::type, index_sequence<2, 3, 4, 5, 6>>::value, "");

// Final test
template struct make_seq<10000>; // This work for me

Upvotes: 1

Related Questions