Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++11 variadic std::function parameter

Tags:

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?

EDIT

I want to make this work for lambdas(both stated and stateless) as well.

like image 595
Daniel K. Avatar asked Feb 11 '12 17:02

Daniel K.


People also ask

How do you declare a variadic function in C++?

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.

Is printf variadic function?

Variadic functions are functions (e.g. printf) which take a variable number of arguments.

How do you get the variable number of arguments in C++?

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.

What is variadic template in C++11?

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;

What is variadic function in C programming?

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.

How to access the arguments of a variadic function?

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.

What is a parameter pack in C++?

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 .


2 Answers

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.

like image 107
Johannes Schaub - litb Avatar answered Sep 17 '22 19:09

Johannes Schaub - litb


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::functions.

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.

like image 25
Potatoswatter Avatar answered Sep 19 '22 19:09

Potatoswatter