распаковка аргументов шаблона переменной для определения новых аргументов шаблона - PullRequest
0 голосов
/ 29 сентября 2018

Я новичок в шаблонном программировании и у меня есть два вопроса ... Надеюсь, кто-нибудь может мне помочь.Я пытаюсь использовать шаблоны с переменными параметрами для создания нового ввода в другой шаблон с переменными параметрами.Другими словами, у меня есть класс

template <std::size_t N, std::size_t... M>
class Class1 {

}

Я хочу использовать целочисленные значения, представленные N, M, чтобы сгенерировать новый набор входных данных типа std :: bitset для другого шаблонного класса

template <typename T, typename... Ts>
class Class2 {

}

Так, например, если я использую Class1<10,20,25>, я хочу внутри тела Class1 создать переменную Class2<std::bitset<10>, std::bitset<20>, std::bitset<25>>.Есть ли простой способ сделать это с помощью C ++ 11?

Мой второй вопрос: как я могу абстрагироваться еще больше, чтобы распаковка не относилась к классу std::bitset?Есть ли способ изменить определение шаблона Class1, чтобы я мог развернуть какой-то произвольный шаблонный класс, который я разработал, вместо std::bitset?

Ответы [ 3 ]

0 голосов
/ 29 сентября 2018

Я считаю, что вы можете думать об операторе ... для пакетов параметров следующим образом:

f(g(Xs)...);

будет расширяться до

f(g(Xs1), g(Xs2), ..., g(Xsn));

для любых операций f и g.На самом деле все, что он делает, это добавляет разделенный запятыми список g, примененный к каждому из предоставленных параметров.Символ ... определяет, с чего следует начинать раскрытие. Эти операции могут быть для типов или значений, поэтому в вашем случае нашим f будет Class2 <...>, а нашим g будет std :: bitset, наш тип будет выглядеть как

Class2<std::bitset<N>, std::bitset<M>...>

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

0 голосов
/ 29 сентября 2018

Другие ответы превосходны, но позвольте мне дать вам еще более общую версию принятого ответа.В основном вы создаете псевдоним с использованием двух шаблонов: первый - это класс, который будет содержать шаблоны классов в качестве параметров шаблона, а второй - шаблон (например, bitset), в который вы хотите передать типы.

template<template<class...> class Y, template<class...> class Z, class... Ts>
using fold_types_into_t = Y<Z<Ts>...>;
template<template<class...> class Y, template<auto...> class Z, auto... Vs>
using fold_values_into_t = Y<Z<Vs>...>;

template<class,class...>
struct Class2;

template <std::size_t N, std::size_t... M>
class Class1 {
  // Class2<std::bitset<10>, std::bitset<20>, std::bitset<25>>
  using T=fold_values_into_t<Class2, std::bitset, N, M...>;
};

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

0 голосов
/ 29 сентября 2018

Вы могли бы написать что-то вроде:

template <std::size_t N, std::size_t... M>
class Class1 {
    template <template <typename, typename...> class C,
              template <std::size_t> class inner>
    using rebind_with_type = C<inner<N>, inner<M>...>;
};

А потом

Class1<10, 20, 25>::rebind_with_type<Class2, std::bit_set>
// -> Class2<std::bit_set<10>, std::bit_set<20>, std::bit_set<25>>

И если вызывать его с зависимым именем, не забудьте typename / template:

typename Class1<N, M...>::template rebind_with_type<Class2, std::bit_set>
// -> Class2<std::bit_set<N>, std::bit_set<M>...>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...