4

I'm trying to use templates in C++ to do the following:

I have a function like this:

template<typename... Args>
void f1(const std::tuple<Args...>& t1);

Inside this function, I would like to create another tuple t2 such that every elements of t1 is copied into t2 at the same position, except for elements of type A, for which t2 should create an object of type B.

However, the constructor of B takes a reference to an object of type A as well as a second argument of type C&. An instance of C is created before the conversion and should be passed as second argument to the constructor of B whenever an object of type A is encountered.

Something like this, only completely generalized:

std::tuple<int, B, double, B> Convert(std::tuple<int, A, double, A> tpl, C& c)
{
  return std::tuple<int, B, double, B>(
    std::get<0>(tpl),
    B(std::get<1>(tpl), c),
    std::get<2>(tpl),
    B(std::get<3>(tpl), c),
  );
}
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
sunmat
  • 6,976
  • 3
  • 28
  • 44
  • 2
    Okay, so what problem have you faced? SO is not a free outsourcing venue. – Lightness Races in Orbit Jul 29 '16 at 16:53
  • I didn't go very far; in other places of my code I had to write template code that manipulates tuples, such as applying a function taking a series of arguments to a tuple containing fields of the same types as the arguments (doing the opposite, that is, converting a series of arguments into a tuple, is easy) so I keep trying to find a way to do the above either assuming that I'm given a tuple t1, or that I have a series of arguments, but I don't go anywhere... – sunmat Jul 29 '16 at 17:16
  • If that silly `C&` thing weren't there, this would be a relatively easy bit of metaprogramming (assuming you have access to C++14, of course). But since that restriction is there, it becomes insanely difficult, since the expressions you use to construct each value now are *different*, depending on the type of that value. You have to find a way to normalize the expression, which requires creating a `tuple`-within-a-`tuple` or something. – Nicol Bolas Jul 29 '16 at 17:24
  • I agree. I may have found a solution, I'll try it and see if it works... – sunmat Jul 29 '16 at 17:25

2 Answers2

3

Note: The new question asks for something more complex. Leaving this answer for those who might benefit.

The power of template conditionals and template pack expansion:

template<typename... Args>
void f1(const std::tuple<Args...>& t1) {
    std::tuple<typename std::conditional<
        std::is_same<A, Args>::value, B, Args>::type...> t2(t1);
    // Both Args are expanded in parallel, resulting in the same types
    // Do things with t2
}
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
  • Thanks, that's a start, but I forgot to mention that the constructor of B takes a const A& and another argument; how can I have the 2nd argument passed to the constructor? – sunmat Jul 29 '16 at 16:26
  • @sunmat: That's a different and more complex question. Can be done anyway though. – Deduplicator Jul 29 '16 at 18:33
1

I guess this would solve the issue:

#include<functional>
#include<tuple>
#include<cassert>

struct A {};
struct C {};
struct B { B(const A &, C &) {} };

template<typename T>
T g(const T &t, C &) { return t; }

B g(const A &a, C &c) {
    return B{a, c};
}

template<std::size_t... I, typename... Args>
void f(const std::tuple<Args...> &tup,std::index_sequence<I...>) {
    C c;
    auto val = std::make_tuple(g(std::get<I>(tup), c)...);
    assert((std::is_same<std::tuple<C, B, C>, decltype(val)>::value));
}

template<typename... Args>
void f(const std::tuple<Args...> &tup) {
    f(tup, std::make_index_sequence<sizeof...(Args)>());
}

int main() {
    auto tup = std::make_tuple(C{}, A{}, C{});
    f(tup);
}

Note that this solution requires C++14, mostly because of std::make_index_sequence and std::index_sequence.
You can find a suitable C++11 implementation of them online if needed.

skypjack
  • 49,335
  • 19
  • 95
  • 187
  • You might want to isolate the mapping in a separate function which is simply invoked by `f` with the proper mapping (defined in a local class). – Deduplicator Jul 30 '16 at 07:06
  • @Deduplicator Yeah, this is a minimal, working example. I don't know how to structure the code for I don't know what's the real world pron. – skypjack Jul 30 '16 at 08:15