1

Let's assume we have a constexpr array as follows:

static constexpr unsigned int a[] = {2, 8, ... ,6}; // N element

I'd like to use this array as template parameter pack:

typedef SomeTemplatedStruct<a[0], a[1], ... ,a[N - 1]> tmp;

It is possible to do so in C++14 as it is explained here. However, I failed to convert that code to C++11. Any help is appreciated.

3
  • 1
    Which part is problematic for you? index_sequence ? Commented Apr 10, 2019 at 1:58
  • Yes, and at the same time, I am hoping to find a more concise way. Commented Apr 10, 2019 at 2:40
  • Example of implementation-c14-make-integer-sequence, and linked solution seems concise enough IMO. Commented Apr 10, 2019 at 9:06

2 Answers 2

2

If you're already going to roll your own, there's no need to implement an integer sequence helper as we can just use the size of the already expanded pack as index for the next element to take out of the array during recursion:

template <typename A, A& a, typename U = typename std::remove_reference<decltype(a[0])>::type, bool = true, U... unpack>
struct unravel;

template <typename T, int N, T (&a)[N], typename U, U... unpack>
struct unravel<T[N], a, U, false, unpack...>
{
    template <template <U...> class Thingie>
    using into = Thingie<unpack...>;
};

template <typename T, int N, T (&a)[N], typename U, U... unpack>
struct unravel<T[N], a, U, true, unpack...> : unravel<T[N], a, U, (sizeof...(unpack) + 1 < N), unpack..., a[sizeof...(unpack)]> {};

usage:

struct Blub
{
    static constexpr unsigned int a[] = {2, 8, 5, 7, 6};
};

template <unsigned int...>
struct TheThingToMake {};

void test()
{
    typename unravel<decltype(Blub::a), Blub::a>::into<TheThingToMake> blub;
}

live example

Note: this won't work with arrays of size 0, but those are non-standard and, I guess, not really an interesting use-case for this anyways…

Sign up to request clarification or add additional context in comments.

Comments

1

The best I can imagine, is develop a C++11 substitute for std::index_sequence and std::make_index_sequence and apply the C++14 solution that you've linked.

But if you avoid it, you can use recursion.

Give an home made integer sequence

template <typename T, T...>
struct myIntegerSequence
 { };

and an helper struct mot_h ("make output template helper")

template <typename T, T, std::size_t, typename>
struct mot_h;

// recursive version
template <typename T, std::size_t N, const T(&A)[N], std::size_t Pos, T ... ts>
struct mot_h<const T(&)[N], A, Pos, myIntegerSequence<T, ts...>>
   : mot_h<const T(&)[N], A, Pos+1u, myIntegerSequence<T, ts..., A[Pos]>>
 { };

// ground case
template <typename T, std::size_t N, const T(&A)[N], T ... ts>
struct mot_h<const T(&)[N], A, N, myIntegerSequence<T, ts...>>
 { using type = myIntegerSequence<T, ts...>; };

you can write the following template output

template <typename T, T inp>
using output = typename mot_h<T, inp, 0u,
   myIntegerSequence<
      typename std::remove_const<
         typename std::remove_reference<decltype(inp[0])>::type>::type>
         >::type;

The following is a full compiling C++11 example

#include <type_traits>

template <typename T, T...>
struct myIntegerSequence
 { };

constexpr int input[] = { 2, 3, 5, 7, 11, 13, 17, 19 };

template <std::size_t N, typename T, const T (&A)[N]>
struct foo
 { };

template <typename T, T, std::size_t, typename>
struct mot_h;

template <typename T, std::size_t N, const T(&A)[N], std::size_t Pos, T ... ts>
struct mot_h<const T(&)[N], A, Pos, myIntegerSequence<T, ts...>>
   : mot_h<const T(&)[N], A, Pos+1u, myIntegerSequence<T, ts..., A[Pos]>>
 { };

template <typename T, std::size_t N, const T(&A)[N], T ... ts>
struct mot_h<const T(&)[N], A, N, myIntegerSequence<T, ts...>>
 { using type = myIntegerSequence<T, ts...>; };

template <typename T, T inp>
using output = typename mot_h<T, inp, 0u,
   myIntegerSequence<
      typename std::remove_const<
         typename std::remove_reference<decltype(inp[0])>::type>::type>
         >::type;

int main ()
 {
   using target = myIntegerSequence<int, 2, 3, 5, 7, 11, 13, 17, 19>;

   static_assert( std::is_same<output<decltype((input)), input>,
                               target>::value, "!" );
 }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.