1

I have searched a lot and could find many similar questions, but none of them solves this particular question AFAIK.

I want to replace a type in a tuple, by type (not by index). I tried something like this:

template <class Tuple, class ToRemove, class ToReplace>
struct ReplaceType {
     using type = Tuple;
};

template <class ToRemove, class ToReplace, class...Args, class...Args2>
struct ReplaceType<std::tuple<Args..., ToRemove, Args2...>, ToRemove, ToReplace> {
    using type = std::tuple<Args..., ToReplace, Args2...>;

};

This won't work but I cannot understand why it should not. It says that parameters are not deducible for Args... and Args2... but to me it should be natural to guess it from the call site:

typename ReplaceType<std::tuple<int, float, char>, float, double>>::type;

From there int should be Args1... in the template specialization and char Args2...

  1. Why this won't work?
  2. Is there any workaround?
Germán Diago
  • 7,473
  • 1
  • 36
  • 59

1 Answers1

2

One step at a time.

First, use specialization to map one type to another, leaving all other types unchanged. If T is ToRemove, replace it with `ToReplace, else leave it alone:

template<typename T, typename ToRemove, typename ToReplace>
struct replace_type {

    using type=T;
};

template<typename ToRemove, typename ToReplace>
struct replace_type<ToRemove, ToRemove, ToReplace> {

    using type=ToReplace;
};

Now, once you've gotten that out of the way, use specialization to unpack the tuple types, then repack them after laundering each one using replace_type:

template<class Tuple, typename ToRemove, typename ToReplace>
struct replace_tuple;

template<typename ...Args, typename ToRemove, typename ToReplace>
struct replace_tuple<std::tuple<Args...>, ToRemove, ToReplace> {

    using type=std::tuple<typename
                  replace_type<Args, ToRemove, ToReplace>::type
                  ...>;
};

Tested with gcc 6.3.1:

replace_tuple<std::tuple<int, char, int>, char, unsigned>::type foo;

std::tuple<int, unsigned, int> *bar=&foo;
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • Trying right now. Why can't directly use what I tried? I would like to get some insight into that as well if possible. Anyway, after trying I am happy to accept the reply because it works. – Germán Diago Jun 19 '17 at 04:02
  • 3
    Because a parameter pack [cannot be deduced unless the pack is the last template parameter](https://stackoverflow.com/questions/14768951/variadic-function-template-with-pack-expansion-not-in-last-parameter), so your `std::tuple` goes down in a flaming wreckage, because it tries to deduce a parameter pack that's not the last template parameter. – Sam Varshavchik Jun 19 '17 at 04:10
  • 1
    Upvoting for the nicely done working implementation and *goes down in a flaming wreckage*. Mostly for the *flaming wreckage* though. – Passer By Jun 19 '17 at 08:36