¿Cómo escribo typedef un puntero de función con C ++ 11 usando la sintaxis?

171

Me gustaria escribir esto

typedef void (*FunctionPtr)();

utilizando using. ¿Como podría hacerlo?

rubenvb
fuente
2
muy conf using, de hecho, especialmente porque los identificadores de puntero de función generalmente residen en el medio de una typedefdeclaración y se mueven al frente usando using. Al menos ahí es donde estoy perdido.
starturtle

Respuestas:

180

Tiene una sintaxis similar, excepto que elimina el identificador del puntero:

using FunctionPtr = void (*)();

Aquí hay un ejemplo

Si quieres "quitar la fealdad", prueba lo que sugirió Xeo:

#include <type_traits>

using FunctionPtr = std::add_pointer<void()>::type;

Y aquí hay otra demostración .

0x499602D2
fuente
25
Dang, esperaba que quitara la fealdad:(
rubenvb
10
@rubenvb:; using FunctionPtr = AddPointer<void()>;)
Xeo
2
Es posible usar alias de tipo de plantilla para limpiar aún más add_pointer<void()>::type: Usando la sugerencia aquí: groups.google.com/a/isocpp.org/d/msg/std-proposals/xDQR3y5uTZ0/… puede escribir pointer<function<void>>.
bames53
55
Estos alias de tipo cambian la sintaxis de tipo de una sintaxis oscura de adentro hacia afuera a una sintaxis simple de izquierda a derecha, lo que elimina en gran medida la necesidad de definiciones de tipo personalizadas para API específicas que facilitan la escritura de los tipos compuestos de esa API.
bames53
10
En C ++ 14, podrá escribir: usando FunctionPtr = std :: add_pointer_t <void ()>;
Andrzej
46

La "fealdad" también se puede eliminar si evita escribir un puntero:

void f() {}
using Function_t = void();    
Function_t* ptr = f;
ptr();

http://ideone.com/e1XuYc

Vadim Goryunov
fuente
Este es un enfoque interesante, aunque me preocuparía olvidarlo *más tarde y obtener errores confusos.
Apollys apoya a Monica el
Esta definitivamente es la mejor versión presentada aquí. Gracias. Y prefiero ver un puntero, ya que es un puntero de función después de todo.
Pierre
13

Desea un type-id, que es esencialmente exactamente lo mismo que una declaración, excepto que elimina el declarator-id. Por declarator-idlo general, es un identificador y el nombre que está declarando en la declaración equivalente.

Por ejemplo:

int x

El declarator-ides xtan solo quítelo:

int

Igualmente:

int x[10]

Eliminar el x:

int[10]

Por su ejemplo:

void (*FunctionPtr)()

Aquí declarator-idestá el FunctionPtr. así que simplemente quítelo para obtener el type-id:

void (*)()

Esto funciona porque type-idsiempre se puede determinar de forma exclusiva dónde iría el identificador para crear una declaración. De 8.1.1 en el estándar:

Es posible identificar de forma exclusiva la ubicación en [id-tipo] donde aparecería el identificador si la construcción fuera una [declaración]. El tipo nombrado es el mismo que el tipo del identificador hipotético.

Andrew Tomazos
fuente
9

¿Qué tal esta sintaxis para mayor claridad? (Nota paréntesis doble)

void func();
using FunctionPtr = decltype((func));
Leo Goodstadt
fuente
1
¿Qué significa el paréntesis doble en este contexto? ¿Una referencia a un puntero de función?
0x499602D2
55
Tu FunctionPtrno es un puntero de función, pero sí decltype(&f), mira aquí .
rubenvb
@ 1234597890 FunctionPtr es una referencia de valor no constante para escribir 'void ()'
Leo Goodstadt
@rubenvb: Tienes razón. No es un puntero de función, sino una referencia de valor de l a la función (tipo). Es por eso que static_assert falla ... <br/> Intente usar FunctionPtr: using namespace std; #include <iostream> void do_f () {cerr << "what? \ n"; } nulo f (); usando FunctionPtr = decltype ((f)); usando FunctionPtr2 = decltype (& f); // No funciona // usando FunctionPtr3 = decltype (f); int main () {FunctionPtr ff = do_f; ff (); FunctionPtr2 ff2 = do_f; ff2 (); }
Leo Goodstadt
1

Otro enfoque podría usar el tipo de retorno automático con el tipo de retorno final.

using FunctionPtr = auto (*)(int*) -> void;

Esto tiene la ventaja discutible de poder decir que algo es una función ptr cuando el alias comienza con "auto (*)" y no está ofuscado por los nombres de los identificadores.

Comparar

typedef someStructureWithAWeirdName& (FunctionPtr*)(type1*, type2**, type3<type4&>);

con

using FunctionPtr = auto (*)(type1*, type2**, type3<type4&>) -> someStructureWithAWeirdName&;

Descargo de responsabilidad: Tomé esto de la charla de Bean Deane "Easing into Modern C ++"

Silvestre
fuente