Да.
Допустим, у меня есть простая переменная структура, которая содержит определение типа:
template<typename... TArgs> struct TupleTypeHolder {
using TupleType = std::tuple<TArgs*...>;
};
Я хочу пройти TupleTypeHolder<something>
в качестве параметра шаблона для другого класса, и получите этот typedef.
Все мои попытки не компилируются.
// None of these is valid
template<template<typename...> class TTupleTypeHolder> struct TupleMaker {
using MyTupleType = TTupleTypeHolder::TupleType; // Not valid
using MyTupleType = typename TTupleTypeHolder::TupleType; // Not valid
};
template<template<typename... A> class TTupleTypeHolder> struct TupleMaker2 {
// A is not a valid name here
using MyTupleType = TTupleTypeHolder<A...>::TupleType; // Not valid
using MyTupleType = typename TTupleTypeHolder<A...>::TupleType; // Not valid
};
Есть ли способ использовать параметры шаблона Variadic (в этом случае, TupleTypeHolder
«s TArgs...
) класса шаблонов с переменными числами из класса, который использует вышеупомянутый класс в качестве параметра шаблона с переменными шаблонами?
Пример использования:
template<typename... TArgs> struct TupleTypeHolder {
using TupleType = std::tuple<TArgs*...>;
};
template<typename... TArgs> static int getSomeValue() { ... }
template<??? T1, ??? T2> class TupleMaker
{
std::pair<int, int> someValues;
using TupleType1 = T1::TupleType;
using TupleType2 = T2::TupleType;
TupleMaker() : someValues{getSomeValue<T1's TArgs...>(),
getSomeValue<T2's TArgs...>()} { }
};
class MyTupleMaker : TupleMaker<TupleTypeHolder<int, char>,
TupleTypeHolder<int, float>>
{ };
MyTupleMaker::TupleType1 tuple1{new int(1), new char('a')};
MyTupleMaker::TupleType2 tuple1{new int(35), new float(12.f)};
Пример использования:
#include <tuple>
template<typename... TArgs> struct TupleTypeHolder {
using TupleType = std::tuple<TArgs*...>;
};
template<typename... TArgs> static int getSomeValue() { return 42; }
// primary template:
template<class T1, class T2>
struct TupleMaker;
// partial specialization:
template<template<class...> class TT1, template<class...> class TT2,
class... T1, class... T2>
struct TupleMaker < TT1<T1...>, TT2<T2...> >
{
std::pair<int, int> someValues;
using TupleType1 = typename TT1<T1...>::TupleType;
using TupleType2 = typename TT2<T2...>::TupleType;
TupleMaker() : someValues{getSomeValue<T1...>(),
getSomeValue<T2...>()} { }
};
struct MyTupleMaker : TupleMaker<TupleTypeHolder<int, char>,
TupleTypeHolder<int, float>>
{ };
MyTupleMaker::TupleType1 tuple1{new int(1), new char('a')};
MyTupleMaker::TupleType2 tuple2{new int(35), new float(12.f)};
int main() {}
Основной шаблон принимает два типа, так как вы передаете типы. TupleTypeHolder<int, char>
это тип, специализация шаблона, а не сам шаблон. шаблон Шаблон-параметры однако возьмите шаблоны в качестве аргументов (не типов), таких как:
template<template<class...> class Foo>
struct Bar
{
using type = Foo<int, double, char>;
};
Bar< std::tuple > b; // note: no template arguments for `std::tuple`!
При частичной специализации вы можете разделить специализацию шаблона на шаблон и параметры, как это работает выше.
Параметры шаблона-шаблона на самом деле не являются параметрами типа, являются параметрами для указания шаблона. Это означает, что то, что вы передаете через параметр template-template, это не тип, а шаблон:
template<template<typename> class TPARAM>
struct give_me_a_template
{
using param = TPARAM; //Error TPARAM is not a type, is a template.
using param_bool = TPARAM<bool>; //OK, thats a type
};
Как видите, первый псевдоним недействителен, поскольку TPARAM не является типом, это шаблон. Но второй тип (является экземпляром шаблона).
Тем не менее, изучить вашу проблему: что вы назвали TupleTypeHolder
может рассматриваться как список типов переменных шаблонов. Итак, ваша цель состоит в том, чтобы создавать кортежи типов, указанных в списках типов, верно?
Вы можете использовать частичную специализацию для извлечения содержимого списка типов:
template<typename TupleTypeHolder>
struct tuple_maker;
template<typename... Ts>
struct tuple_maker<TupleTypeHolder<Ts...>>
{
using tuple_type = std::tuple<Ts...>;
};
Примером его использования может быть:
using my_types = TupleTypeHolder<int,int,int>;
using my_tuple_type = typename tuple_maker<my_types>::tuple_type;
Конечно, это не совсем решение вашей реализации, вам нужно расширить концепцию до нескольких списков типов (как показал ваш вопрос). То, что я предоставил, является руководством, чтобы понять проблему и ее решение.