Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get variadic template variadic template parameter variadic parameters

Yes.

Let's say I have a simple variadic struct that holds a typedef:

template<typename... TArgs> struct TupleTypeHolder {
    using TupleType = std::tuple<TArgs*...>;
};

I want to pass TupleTypeHolder<something> as a template parameter to another class, and get that typedef.

All of my tries do not compile.

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

Is there a way to use the variadic template parameters (in this case, TupleTypeHolder's TArgs...) of a variadic template class from a class that uses the aforementioned class as a template variadic template parameter?


Usage example:

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)};  
like image 600
Vittorio Romeo Avatar asked Jan 24 '26 13:01

Vittorio Romeo


1 Answers

Working usage example:

#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() {}

The primary template takes two types, as you're passing types. TupleTypeHolder<int, char> is a type, a specialization of a template, not a template itself. Template template-parameters however take templates as arguments (not types), such as:

template<template<class...> class Foo>
struct Bar
{
    using type = Foo<int, double, char>;
};

Bar< std::tuple > b; // note: no template arguments for `std::tuple`!

With partial specialization, you can split a template specialization into the template and the parameters, that's how the above works.

like image 68
dyp Avatar answered Jan 26 '26 07:01

dyp



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!