user975989
user975989

Reputation: 2648

How do I create a type list to expand into a tuple?

I am trying to create a class that has a tuple of all the types that are passed to it. I want it to take a type list as a template parameter, and use the classes within that list as the classes an internal tuple will contain. Currently, I have something like this, which doesn't actually compile.

template<class ... T>
struct ComponentList {};

template<ComponentList<typename ...T> >
class ComponentManager{
    std::tuple<T...> components;
};

The reason I want to have ComponentList be its own type is because I want to also pass in other type lists later. Is this possible? If not, what would be an alternative that will work?

Upvotes: 9

Views: 2067

Answers (2)

Jon Purdy
Jon Purdy

Reputation: 55049

You can add a template to rebind the parameters from your type-level list into std::tuple:

template<class A, template<class...> class B>
struct rebind_;

template<template<class...> class A, class... T, template<class...> class B>
struct rebind_<A<T...>, B> {
    using type = B<T...>;
};

template<class A, template<class...> class B>
using rebind = typename rebind_<A, B>::type;

Then use it like so:

template<class... T>
struct ComponentList {};

template<class List>
struct ComponentManager {
    rebind<List, std::tuple> components;
};

int main() {
    using List = ComponentList<int, char, long>;
    ComponentManager<List> manager;
    std::cout << std::get<0>(manager.components) << '\n';
}

I guess if you want to enforce that the original type is ComponentList, you can use enable_if and is_instantiation_of:

template<class List,
    typename = std::enable_if<is_instantiation_of<List, ComponentList>::value>::type>
struct ComponentManager {
    rebind<List, std::tuple> components;
};

Upvotes: 10

Claudiu
Claudiu

Reputation: 229491

Would you be able to enforce that all your typelist classes provide a tuple_t type, with their internal types? Something like:

template <class ... T>
struct ComponentList {
    typedef std::tuple<T...> tuple_t;
};

template<class T>
class ComponentManager {
    typename T::tuple_t components;
};

Usage is what you'd expect:

ComponentManager<ComponentList<int, double> > cm;

Upvotes: 2

Related Questions