2011-08-30 6 views
15

que estoy acostumbrado a ver la sintaxis como esta para los punteros de funciónSintaxis de plantillas de C++ con parámetros de tipo de función

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

En algunas bibliotecas funcionales C++ 03 que veo tipos utilizados de esta manera:

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

en C++ de 11 std::function veo el tipo determinado de esta manera

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

Hay una falta (*). ¿Por qué?

El C++ 03 function<T> tiene T siendo un tipo idéntico al puntero de función correspondiente. Es fácil imaginar la implementación.

std::function en C++ 11 es compatible con las mejoras del lenguaje central. ¿Se han ampliado los tipos de argumento de la plantilla para que se ajusten a la capacidad de invocación?

Respuesta

17

std::function (y su inspiración, boost::function) no solo almacena punteros de función. También puede almacenar objetos de función. En ese sentido, pasar una como firma de la función es similar a la forma en que un puntero inteligente suele tomar el tipo del punta como un parámetro de plantilla, ¡no como un tipo de puntero!

Contraste:

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

con

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; 

Esta es una convención útil.

+0

Esto es mucho mejor que el libro de texto puntero a la sintaxis! Me pregunto por qué no lo enseñamos de esta manera normalmente ... – spraff

+1

@spraff: Probablemente porque es una innovación relativamente reciente, y la mayoría de los libros de texto tienen una rotación muy lenta. Todavía veo gente aprendiendo con Borland Turbo C++, que parece tener un gran problema con esta sintaxis. – greyfade

3

Los tipos de funciones no son nuevos en C++ 11 (consulte 8.3.5 en C++ 98). IIRC, la mejora sobre lo que TR1 y boost proporcionan para function son bastante menores.

8

No hay nada mágico aquí, el tipo

void(int,float) 

es el tipo de una función sin los nombres. Concuerda con una función como void g(int x, float y).

Con plantillas que no tienen para usar punteros a funciones, también puede usar tipos de funciones.

8

Al igual que con otros elementos, las funciones tienen un tipo, y puede usar el tipo o el puntero al tipo en diferentes contextos. El (*) faltante que está esperando es solo el puntero a la sintaxis.

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

Los tipos de pointer_name y pointer_name2 son los mismos: puntero a una función que devuelve int y toma dos argumentos de tipos float y char*.Tenga en cuenta que esto es exactamente equivalente a otros tipos como int, con la diferencia de que no puede declarar que una variable sea del tipo función, solo puntero a la función.

La interfaz de std::function (o boost::function) sólo se necesita la firma de la función. El argumento de tipo no es un puntero para funcionar sino más bien el tipo de una función (como my_function_type en el código anterior)

Cuestiones relacionadas