Transform algorithm on a variadic template

486 views Asked by At

I am using C++11, and I need something like transform (the stl algorithm of containers) that can transform a template<typename ...T> into <typename ...T::something> so I can use it for inheritance :

for example:

template<typename T>
struct typeOf{
   using type = T;
};

template<typename ...T> // All the arguments must be `typeOf`'s
class tupleOf : tuple<T::type...>{
}

so that :

tupleOf<typeOf<int>,typeOf<char>> would give me a tuple<int,char>

I want to do this without using C++14 features

3

There are 3 answers

0
Jarod42 On BEST ANSWER

You may do something like:

template <typename T, template <typename> class f>
struct transform;


template <template <typename...> class C, typename...Ts, template <typename> class f>
struct transform<C<Ts...>, f>
{
    using type = C<typename f<Ts>::type...>;
};

And usage:

static_assert(std::is_same<std::tuple<char, int>,
                           transform<std::tuple<char*, int*>, 
                                     std::remove_pointer>::type>::value,
              "unexpected");

Live Demo.

0
TartanLlama On

If you are just looking for a simple solution to your particular issue, this should work for you:

namespace detail {
    //primary template for when something invalid is passed
    //could add a static_assert to improve compiler message
    template<typename... T> struct tupleOf;

    //partial specialization for when a list of typeOf types are passed
    template<typename... Ts>
    struct tupleOf<typeOf<Ts>...>
    {
        using type = std::tuple<Ts...>;
    };
}

//alias template for ease-of-use
template <typename... Ts>
using tupleOf = typename detail::tupleOf<Ts...>::type;

Now tupleOf<typeOf<int>,typeOf<char>> is equivalent to std::tuple<int,char>.

0
Sebastian Redl On

Simple transforms already work in the context of pattern expansions. Your original code should work just fine if you just add a typename keyword.

template<typename T>
struct typeOf{
   using type = T;
};

template<typename ...T> // All the arguments must be `typeOf`s
class tupleOf : tuple<typename T::type...>{
};

Although a template alias is probably the better choice.

template <typename... T>
using tupleOf = tuple<typename T::type...>;