A function named test
takes std::function<>
as its parameter.
template<typename R, typename ...A> void test(std::function<R(A...)> f) { // ... }
But, if I do the following:
void foo(int n) { /* ... */ } // ... test(foo);
Compiler(gcc 4.6.1) says no matching function for call to test(void (&)(int))
.
To make the last line test(foo)
compiles and works properly, how can I modify the test()
function? In test()
function, I need f
with type of std::function<>
.
I mean, is there any template tricks to let compiler determine the signature of function(foo
in example), and convert it to std::function<void(int)>
automatically?
I want to make this work for lambdas(both stated and stateless) as well.
Variadic functions are functions (e.g. std::printf) which take a variable number of arguments. To declare a variadic function, an ellipsis appears after the list of parameters, e.g. int printf(const char* format...);, which may be preceded by an optional comma.
Variadic functions are functions (e.g. printf) which take a variable number of arguments.
Variable number of arguments in C++Define a function with its last parameter as ellipses and the one just before the ellipses is always an int which will represent the number of arguments. Create a va_list type variable in the function definition. This type is defined in stdarg. h header file.
Variadic template is a template, which can take an arbitrary number of template arguments of any type. Both the classes & functions can be variadic. Here's a variadic class template: template<typename... Arguments> class VariadicTemplate; is also valid C++11. template<typename T, typename... Arguments> class VariadicTemplate;
Variadic functions are functions that can take a variable number of arguments. In C programming, a variadic function adds flexibility to the program. It takes one fixed argument and then any number of arguments can be passed. The variadic function consists of at least one fixed variable and then an ellipsis (…) as the last parameter.
The variadic function consists of at least one fixed variable and then an ellipsis (…) as the last parameter. int function_name (data_type variable_name, ...); Values of the passed arguments can be accessed through the header file named as: This enables access to variadic function arguments. This one accesses the next variadic function argument.
Parameter pack. (since C++11) sizeof... (C++11) A template parameter pack is a template parameter that accepts zero or more template arguments (non-types, types, or templates). A function parameter pack is a function parameter that accepts zero or more function arguments. A template with at least one parameter pack is called a variadic template .
It looks like you want to use overloading
template<typename R, typename ...A> void test(R f(A...)) { test(std::function<R(A...)>(f)); }
This simple implementation will accept most if not all the functions you will try to pass. Exotic functions will be rejected (like void(int...)
). More work will give you more genericity.
std::function
implements the Callable interface, i.e. it looks like a function, but that doesn't mean you should require callable objects to be std::function
s.
template< typename F > // accept any type void test(F const &f) { typedef std::result_of< F( args ) >::type R; // inspect with traits queries }
Duck typing is the best policy in template metaprogramming. When accepting a template argument, be unspecific and just let the client implement the interface.
If you really need a std::function
for example to re-target the variable or something crazy like that, and you know the input is a raw function pointer, you can decompose a raw function pointer type and reconsitute it into a std::function
.
template< typename R, typename ... A > void test( R (*f)( A ... ) ) { std::function< R( A ... ) > internal( f ); }
Now the user can't pass a std::function
because that has been encapsulated within the function. You could keep your existing code as another overload and just delegate to that, but be careful to keep interfaces simple.
As for stateful lambdas, I don't know how to handle that case. They don't decompose to function pointers and as far as I know the argument types cannot be queried or deduced. This information is necessary to instantiate std::function
, for better or worse.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With