Преобразование статического массива constexpr в параметр шаблона в С++ 11

Предположим, у нас есть массив 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. Любая помощь приветствуется.

Какая часть для вас проблематична? index_sequence ?

Jarod42 10.04.2019 03:58

Да, и в то же время я надеюсь найти более лаконичный способ.

MTMD 10.04.2019 04:40

Пример реализация-c14-сделать-целочисленная-последовательность и связанное решение кажется достаточно кратким IMO.

Jarod42 10.04.2019 11:06
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
442
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

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

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

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

и вспомогательная структура mot_h («сделать помощником шаблона вывода»)

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, "!" );
 }
Ответ принят как подходящий

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

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, но они нестандартны и, я думаю, в любом случае не очень интересный вариант использования для этого…

Другие вопросы по теме