Reputation: 626
I have the following function
template <typename... Args>
void func(Args&&... args){
// do stuff
}
I now want to create a function pointer, that is callable with a variadic list of arguments, just like the function itself.
template <typename... Args>
using Var_Func = void(*)(Args... args)
At this point, I'm stuck. When creating a variable of type Var_Func
, I have to give a list of types for the template:
Var_Func<[List of types]> var_func_p = &func;
This, however, prevents me from calling the pointer with a true variadic list of arguments. I want a pointer, that allows me to call it like a true variadic function, like this:
var_func_p("Test");
var_func_p(0.3, 5);
var_func_p('c', "Another test", 1.3, 3);
I have no idea how to achieve this. Can someone help me?
Upvotes: 0
Views: 233
Reputation: 11230
Simply put, this is not possible.
A function template is not a function, it's a template of a function -- and thus it does not have a function pointer until you specify which instantiation you want. At which point, the pointer is fixed to a specific number of arguments of specific types.
It is not possible in the C++ language to type-erase templates into a singular type, such as a pointer that you can pass around and lazily instantiate.
That is, code such as:
some_discrete_variadic_type x = var_func_1;
x(1);
x(1, "2");
x = var_func_2;
x(1);
x(1, "2");
Is not possible, because for type-erasure to work you must normalize the erasure to a fixed number of types (in this case, it would be instantiations).
Depending on what the problem is you are trying to solve, however, there might be workarounds -- though this would require more information.
If your uses are more limited -- such as to pass the functionality into other functions that are only ever known at compile-time, then you can use Functor objects instead and pass them into function templates where the arguments are deduced. For example:
struct var_func
{
template <typename...Args>
auto operator()(Args&&...args) -> void
{
// do something
}
};
Where an example of it being called could be:
template <typename T>
auto consume(T var_func_p) -> void
{
var_func_p("Test");
var_func_p(0.3, 5);
var_func_p('c', "Another test", 1.3, 3);
}
int main()
{
consume(var_func{});
consume(some_other_var_func{});
}
Note that in this case, you're not passing a function template around anymore. You're passing a static object, var_func
, which contains a call-operator (operator()
) that is a function template.
Upvotes: 3
Reputation: 58929
func
isn't actually a function. It's a template that the compiler can use to create new functions when it needs to.
When you do func(5)
the compiler creates a function called func<int>
and then calls it. When you do func(5.0, 'a')
the compiler creates a function called func<double, char>
and then calls it. These are two completely different, unrelated functions with two different types.
You can create a pointer to func<int>
or func<double, char>
or func<>
or func<anything else>
in the usual way. But you cannot ever create a pointer to func
, because func
is not a function, it's an instruction for the compiler.
Upvotes: 3
Reputation: 123129
Like this:
template <typename... Args>
void func(Args&&... args){
// do stuff
}
template <typename... Args>
using f_ptr = void(*)(Args&&...);
int main() {
f_ptr<int,int> p = &func<int,int>;
p(3,1);
}
However, pointers to different instantations of func
are incompatible.
This, however, prevents me to call the pointer with a true variadic list of arguments. I want a pointer, that allows me to call it like a true variadic function, like this:
You cannot store a pointer to eg func<double,double>
in a f_ptr<int,int>
.
Upvotes: 2