I'm not sure what I want to achieve is possible, but I need my templated function (my_func
) to be able to take both variable arguments as well as a tuple argument. Clearer description is in the code comments.
struct A{
static void call_func(int a, std::string b) {
std::cout<<"int is: "<<a<<", string is: "<<b<<"\n";
}
};
struct B{
static void call_func(std::string a, std::string b) {
std::cout<<"string is: "<<a<<", string is: "<<b<<"\n";
}
};
struct C{
static void call_func(int a) {
std::cout<<"int is: "<<a<<"\n";
}
};
template<typename T, typename... Args>
void my_func(Args... args) {
T::call_func(args...);
}
int main() {
my_func<A>(3, "ant"); //int is: 3, string is: ant
my_func<B>("bat", "bee"); //string is: bat, string is: bee
my_func<C>(5); //int is: 5
//Is there a way to call(or modify) my_func such that it also accepts a tuple
std::tuple<int, std::string> a_params{3,"tuple-ant"};
std::tuple<std::string, std::string> b_params{"tuple-bat","tuple-bee"};
std::tuple<int> c_params{7};
// my_func<A>(a_params);
// my_func<B>(b_params);
// my_func<C>(c_params);
}
CodePudding user response:
Are you sure it's a good idea that both functions are called my_func()
? To avoid confusion, what about my_func_tuple()
, or something similar, for the second one?
Anyway... it seems to me that you're looking for std::apply()
; with it the tuple version can be written as
template <typename T, typename ... Args>
void my_func(std::tuple<Args...> tpl) {
std::apply(T::call_func, tpl);
}
Take in count that std::apply()
is available starting from C 17; before C 17 (C 11 and C 14) you have to simulate it using a integer sequence; see the Mooing Duck answer for a good example.
CodePudding user response:
This is almost exactly what integer_sequence
was made for:
template<typename T, typename... Args, std::size_t... ints>
void my_func(std::tuple<Args...> args, std::integer_sequence<std::size_t,ints...> sequence) {
T::call_func(std::get<ints>(args)...);
}
std::get<ints>(args)...
says for each item in the size_t...ints
template parameter, call get<ints>(args)
. This lets you unpack args as a list of parameters to the method. But then we have to figure out how to make the right integer_sequence
. Luckily, that's also easy:
template<typename T, typename... Args>
void my_func(std::tuple<Args...> args){
my_func<T, Args...>(args, std::make_index_sequence<sizeof...(Args)>{});
}