3

I want to create a function that changes multiple values inside a tuple with one call.

template<class... Args>
class EventN {
public:
  std::tuple<Args...> mArgs;

  EventN(Args... args) : mArgs(args) {}
  EventN() {}

  template<size_t N> void set(typename std::tuple_element<N-1,Tuple>::type value) {
     std::get<N-1>(mArgs) = value; //I use N-1, to start from '1'
  }

};

The set function above works as I expect it to:

auto event = new EventN<String,int>();
event->set<1>("testEvent");
event->set<2>(12);

Now, I want to extend the function to:

event->set<1,2>("testEvent", 12);

How can I achieve that? Is there a way to make std::tuple_element<N-1,Tuple>::type variadic?

Gasim
  • 7,615
  • 14
  • 64
  • 131

1 Answers1

5

Try something like this:

template <int ...N, typename ...Args>
void set_all(Args &&... args)
{
    int dummy[] = { (set<N>(std::forward<Args>(args)), 0)... };
    static_cast<void>(dummy);   // unused
}

This works because the different packs are expanded in lockstep. This requires all packs to have the same size, which is enforced at compile time.

The dummy array and the comedic comma operator are just a sleazy way of evaluating all the expressions for their side effects' sake without caring for their value.

Here's a complete little demo:

#include <iostream>
#include <utility>

template <int N, typename T> void set(T && t)
{
    std::cout << "Setting " << N << " => " << std::forward<T>(t) << "\n";
}

template <int ...N, typename ...Args>
void set_all(Args &&... args)
{
    int dummy[] = { (set<N>(std::forward<Args>(args)), 0)... };
    static_cast<void>(dummy);
}

int main()
{
    set_all<2, 51, 1>("Hello", 100, true);
}

Observe that at this point there is no constraint on the values of the integers; this constraint only comes in later when you use the integer as a tuple index.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • what is `std::set_all`? I can't seem to find any reference about it. Or did you mean `set_all_wrapper`? – Gasim Dec 30 '13 at 17:48
  • can you please elaborate why we need to use an array of ints' – Gasim Dec 30 '13 at 18:02
  • @Gasim: I've simplified it a lot. You can expand multiple packs at once in lockstep provided they have the same size. – Kerrek SB Dec 30 '13 at 18:06
  • yeah im going through the code. I still don't understand the point of using the dummy array. Does it play a role of the loop? If yes, what about using recursive function for that... – Gasim Dec 30 '13 at 18:11
  • @Gasim: You could indeed use a recursive function instead of the dummy array; but the dummy array is simpler to use. – Matthieu M. Dec 30 '13 at 18:12