c++templatesc++11variadic-templatestypelist

From typelist to argument pack


I have a typelist of the form described here:

http://www.drdobbs.com/generic-programmingtypelists-and-applica/184403813

Each type has a duck-typed function (template/compile-time virtual) called get() which returns a simple type like this:

struct Float {
  float get() { return 7.0; }
};
struct Int {
  int get() { return 7; }
};
typedef typelist<Float, typelist<Int, null_typelist>> types;

I also have a function that takes a variadic number of simple type arguments, like this:

template<typename... Args>
foo(Args... args)
{
}

Now I need a way to call foo given types. I think there's a solution to this, via a tuple, but I'm really far from a solution that works... I hope you can help me here!


Solution

  • This code converts typelist to tuple and calls foo with simple types.

    #include <tuple>
    #include <iostream>
    
    template<typename H, typename T>
    struct typelist
    {
        typedef H Head;
        typedef T Tail;
    };
    
    struct null_typelist {};
    
    
    template<int... Indices>
    struct indices {
        using next = indices<Indices..., sizeof...(Indices)>;
    };
    
    template<int Size>
    struct build_indices {
        using type = typename build_indices<Size - 1>::type::next;
    };
    
    template<>
    struct build_indices<0> {
        using type = indices<>;
    };
    
    template<typename T>
    using Bare = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
    
    template<typename Tuple>
    constexpr
    typename build_indices<std::tuple_size<Bare<Tuple>>::value>::type
    make_indices()
    { return {}; }
    
    template<typename T, typename... Args>
    struct tuple_push;
    
    template<typename T, typename... Args>
    struct tuple_push<T, std::tuple<Args...>>
    {
        typedef std::tuple<Args..., T> type;
    };
    
    template<typename TL>
    struct typelist_to_tuple;
    
    template<typename H, typename T>
    struct typelist_to_tuple<typelist<H, T>>
    {
        typedef typename tuple_push<H, typename typelist_to_tuple<T>::type>::type type;
    };
    
    template<typename H>
    struct typelist_to_tuple<typelist<H, null_typelist>>
    {
        typedef std::tuple<H> type;
    };
    
    struct Float {
      float get() const { return 7.5; }
    };
    struct Int {
      int get() const { return 7; }
    };
    
    template<typename... Args>
    void foo(const Args&... args)
    {
    }
    
    template<typename T, typename... Args>
    void foo(const T& current, const Args&... args)
    {
        std::cout << current << std::endl;
        foo(args...);
    }
    
    template<typename Tuple, int... Indices>
    void apply(const Tuple& tuple, indices<Indices...>)
    {
        foo(std::get<Indices>(tuple).get()...);
    }
    
    template<typename Tuple>
    void apply(const Tuple& tuple)
    {
        apply(tuple, make_indices<Tuple>());
    }
    
    int main()
    {
        typedef typelist<Int, typelist<Float, typelist<Int, null_typelist>>> list;
        typedef typelist_to_tuple<list>::type tuple;
        tuple t = std::make_tuple(Int(), Float(), Int());
        apply(t);
    }
    

    live example