распаковка аргументов variadic template для определения новых аргументов шаблона

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

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 ответов


вы можете написать что-то вроде:

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

Я нахожу, что вы можете думать об этом ... оператор на пакетах параметров таким образом:

f(g(Xs)...);

расширится до

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

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

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

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


другие ответы превосходны, но позвольте мне дать вам еще более общую версию принятого ответа. Вы в основном создаете псевдоним using, который принимает два шаблона, первый-это класс, который будет содержать шаблоны классов в качестве параметров шаблона ,а второй-шаблон (например,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...>;
};

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