Преобразование статического массива constexpr в параметр шаблона в C ++ 11 - PullRequest
1 голос
/ 10 апреля 2019

Предположим, у нас есть массив constexpr следующим образом:

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

Я хотел бы использовать этот массив в качестве пакета параметров шаблона:

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

Это можно сделать в C ++ 14, как объяснено здесь . Однако мне не удалось преобразовать этот код в C ++ 11. Любая помощь приветствуется.

Ответы [ 2 ]

2 голосов
/ 10 апреля 2019

Если вы уже собираетесь создавать свои собственные, нет необходимости реализовывать помощник целочисленной последовательности, поскольку мы можем просто использовать размер уже расширенного пакета в качестве индекса для следующего элемента, который будет извлечен из массива во время рекурсии:

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)]> {};

использование:

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;
}

живой пример

Примечание: это не будет работать с массивами размера 0, но ониНестандартный и, я думаю, не очень интересный вариант использования для этого в любом случае ...

1 голос
/ 10 апреля 2019

Лучшее, что я могу себе представить, это разработать заменитель C ++ 11 для std::index_sequence и std::make_index_sequence и применить решение C ++ 14, которое вы связали.

Но если этого избежать, вы можете использовать рекурсию.

Дать самодельную целочисленную последовательность

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

и вспомогательную структуру mot_h ("make output templatehelper ")

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...>; };

вы можете написать следующий шаблон 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;

Ниже приведен пример полной компиляции C ++ 11

#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, "!" );
 }
...