问题
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?
回答1:
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.
来源:https://stackoverflow.com/questions/20844519/how-to-assing-multiple-stdtuple-element-as-function-arguments-using-variadic-s