3

I have an std::tuple given like this:

typedef std::tuple<t1, t2, t3> tuple_t;

Now, I want to transform t3_tuple into a similar tuple:

typedef std::tuple< T<t1>, T<t2>, T<t3> > derived_tuple_t;

In my case, for example, t1, t2, and t3 are primitives, and T is std::stack. In general, assume that that there might be t4 and so on.

Of course, my second definition already solves the problem, but I'd like the deriving to be automatic: Given only T and tuple_t, build me derived_tuple_t. Like this:

template <class T, class tuple_t> using derived_tuple_t = std::tuple</*???*/>;

Is something like this possible? Maybe a short solution?

Morwenn
  • 21,684
  • 12
  • 93
  • 152
Johannes
  • 2,901
  • 5
  • 30
  • 50

2 Answers2

4

You could declare struct update_tuple with two template parameters:

  1. T - will be templated, and this parameter we will apply to the parameters in the tuple
  2. std::tuple with a variable number of template parameters.

Then just create an alias for a new tuple with arguments applied with T using pack expansion

#include <tuple>
#include <type_traits>
#include <vector>

template <template<class...> class, class>
struct update_tuple;

template <template <class...> class T, class... Args>
struct update_tuple<T, std::tuple<Args...>>
{
    using type = std::tuple<T<Args>...>;
};

int main()
{
    static_assert
    (
        std::is_same
        <
            std::tuple<std::vector<int>, std::vector<double>>,
            update_tuple<std::vector, std::tuple<int, double>>::type
        >::value,
        "They are not same"
    );
    return 0;
}

Thanks to @Xeo: Code will not fails if T could accept more than one template parameter(when others but first has defaults).

Example

awesoon
  • 32,469
  • 11
  • 74
  • 99
  • I think it would be nice to mention the word template template parameter and give some explanation... – jogojapan Jun 14 '13 at 08:29
  • @jogojapan, _"I think it would be nice to mention the word template template parameter"_ - would it? We do not use it anywhere. – awesoon Jun 14 '13 at 08:37
  • @soon This is just an inductive declaration, right? Just for fun: Do you know if it is true to avoid the class keyword at all? – Johannes Jun 14 '13 at 08:37
  • 2
    @soon: `template class T` is a template, and as a parameter *of* a template, it's a *template template parameter*. :) Also note that your code will fail for class templates that take more than one argument, but have defaults for everyone but the first (like standard sequence containers). – Xeo Jun 14 '13 at 08:41
  • @soon Not sure if I understand. But my point was that the answer seemed to consist only of code. I am in favor of answers that use language to explain things as well. You are obviously free to disagree. – jogojapan Jun 14 '13 at 08:41
  • @soon Accepted the other answer. It was more complete. Thanks, still! – Johannes Jun 14 '13 at 09:01
  • @Johannes, No problems. I'm glad if my answer was helpful for you. – awesoon Jun 14 '13 at 09:08
  • @Xeo, Not sure if I understand your first part correctly. Couldn't you check my answer again? Thanks anyway. – awesoon Jun 14 '13 at 09:10
  • @soon: "Template template parameter" is just the name of the such a parameter (`T` in your case, and `TT` in mine). – Xeo Jun 14 '13 at 09:15
3

A little partial specialization using template template parameters should do the job (generalized to variadic templates, not only tuples):

template<template<class...> class TT, class ArgsT>
struct make_over;

template<template<class...> class TT, template<class...> class ArgsT, class... Ts>
struct make_over<TT, ArgsT<Ts...>>{ using type = ArgsT<TT<Ts>...>; };

template<template<class...> class TT, class ArgsT>
using MakeOver = typename make_over<TT, ArgsT>::type;

Note that this can be problematic with stdlibs that don't use true variadic templates, and emulate it instead with macro machinery and default template arguments (like MSVC).

Live example.

Xeo
  • 129,499
  • 52
  • 291
  • 397
  • Can you please elaborate on why this might not work with MSVC? What does it mean that they do not use "true variadic templates"? – Johannes Jun 14 '13 at 08:36
  • 1
    @Johannes: MSVC's stdlib uses `template class tuple;` and then partial specializations up to a certain limit to emulate variadic templates. A trait such as the above used on a `tuple` will result in a `tuple, X, X<_Nil>, X<_Nil>...>` which will screw everything over. – Xeo Jun 14 '13 at 08:37
  • is this a misbehavior of MSVC, which might be fixed by them in the future? – Johannes Jun 14 '13 at 08:40
  • @Johannes: Sure, if they support variadic templates. :) The standard demands that tuple is implemented as `template class tuple;`. – Xeo Jun 14 '13 at 08:42
  • Thanks! Do you see a solution without using the struct/class keywords at all? – Johannes Jun 14 '13 at 08:45
  • 1
    @Johannes: You mean without any metafunction and only using-aliases? No, since no such functionality exists yet in the standard library. – Xeo Jun 14 '13 at 08:56