Syntax of C++ templates with function type paramet

2020-02-07 00:23发布

问题:

I'm used to seeing syntax like this for function pointers

int (*pointer_name) (float, char *);
void call_function (void (*)(int), int);

In some C++03 functional libraries I see types used this way:

abc::function<void(*)(int,float)> f;

In C++11's std::function I see the type given this way

std::function<void(int,float)> f;

There is a missing (*). Why?

The C++03 function<T> has T being an identical type to the corresponding function pointer. It's easy to imagine the implementation.

std::function in C++11 is supported by core language enhancements. Have template argument types been extended to accomodate callability?

回答1:

std::function (and its inspiration, boost::function) does not only store function pointers. It can also store function objects. In that sense, passing a function signature as a template parameter is similar to how a smart pointer usually take the type of the pointee as a template parameter, not a pointer type!

Contrast:

int* p; // indirection to an object of type int
std::unique_ptr<int> q; // indirection to an object of type int

with

typedef void signature_type(); // a function type

// indirection to something callable with signature_type as a signature
// i.e. f() has type void
// only work for freestanding functions however
signature_type* f;

// indirection to something callable with signature_type as a signature
// i.e. g() has type void
// not restricted to function pointers!
std::function<signature_type> g;

This is a useful convention.



回答2:

There is nothing magic here, the type

void(int,float)

is the type of a function without the names. It matches a function like void g(int x, float y).

With templates you don't have to use function pointers, you can use function types as well.



回答3:

As with other elements, functions have a type, and you can use either the type or the pointer to the type in different contexts. The missing (*) you are expecting is just the pointer-to syntax.

int (*pointer_name) (float, char *);
typedef int my_function_type(float,char*);
my_function_type * pointer_name2;

The types of pointer_name and pointer_name2 are the same: pointer to a function that returns int and takes two arguments of types float and char*. Note that this is exactly equivalent to other types like int, with the difference that you cannot declare a variable to be of type function, only pointer to function.

The interface of std::function (or boost::function) just takes the signature of the function. The type argument is not a pointer to function but rather the type of a function (like my_function_type in the code above)



回答4:

Function types aren't new in C++11 (see 8.3.5 in C++98). IIRC, the improvement over what TR1 and boost provide for function are quite minor.