pointer c++ types language-lawyer function-pointers

function pointer c++



¿Diferencia de tipo entre “diversión” y “y diversión”? (3)

Ambas aserciones tienen éxito porque se aplican al tipo T deducido de un argumento de función. En ambos casos, se deducirá como un puntero para funcionar porque las funciones decaen a un puntero para funcionar. Sin embargo, si reescribe las afirmaciones para aceptar tipos directamente, la primera fallará:

static_assert(is_same<void(*)(), decltype(fun)>::value); static_assert(is_same<void(*)(), decltype(&fun)>::value);

compilador en línea

¿Las expresiones fun y &fun tienen el mismo tipo o no?

Considera el siguiente código:

template <typename Check, typename T> void check(T) { static_assert(is_same<Check, T>::value); } void fun() {} check<void(*)()>(fun); check<void(*)()>(&fun); cout << typeid(fun).name() << endl; cout << typeid(&fun).name() << endl;

Ambas aserciones tienen éxito, lo que sugiere que ambas expresiones tienen el mismo tipo. Sin embargo, typeid s devuelve resultados diferentes:

FvvE PFvvE

¿Porqué es eso?


Cuando utiliza un nombre de función como expresión, se desintegra a un puntero a sí mismo. Así que la fun será igual que la &fun .

En cuanto a lo typeid , a partir de typeid :

Las conversiones Lvalue-to-rvalue, array-to-punter o function-to-puntero no se realizan.

[Énfasis mío]


fun y &fun refieren al mismo tipo debido a la conversión de función a puntero , que se realiza en check<void(*)()>(fun); ; pero typeid es una excepción.

(énfasis mío)

Las conversiones Lvalue-to-rvalue, array-to-punter o function-to-puntero no se realizan .

Y por qué la conversión de función a puntero se realiza para check<void(*)()>(fun); , porque en la plantilla de deducción de argumentos ,

Antes de que comience la deducción, se realizan los siguientes ajustes a P y A :

1) Si P no es un tipo de referencia,

  • si A es un tipo de matriz, ...;
  • de lo contrario, si A es un tipo de función, A se reemplaza por el tipo de puntero obtenido de la conversión de función a puntero;

check() toma el parámetro por valor, luego se realiza la conversión de la función a puntero y el tipo deducido de T también será el puntero de la función, es decir, void(*)() .