Faire des expressions fun
et &fun
ont le même type ou pas?
Considérez le code suivant:
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;
Les deux assertions réussissent, ce qui suggère que les deux expressions ont le même type. Cependant, typeid
s renvoie des résultats différents:
FvvE
PFvvE
Pourquoi donc?
Les deux assertions réussissent car elles sont appliquées au type T
déduit de l'argument de fonction. Dans les deux cas, il sera déduit comme un pointeur pour fonctionner car les fonctions se désintègrent en un pointeur pour fonctionner. Cependant, si vous réécrivez des assertions pour accepter directement des types, la première échouera:
static_assert(is_same<void(*)(), decltype(fun)>::value);
static_assert(is_same<void(*)(), decltype(&fun)>::value);
fun
et &fun
font référence au même type en raison de conversion de fonction en pointeur , qui est effectuée dans check<void(*)()>(fun);
; mais typeid
est une exception.
(c'est moi qui souligne)
Les conversions de fonction en pointeur de Lvalue en rvalue, de tableau en pointeur ou ne sont pas effectuées .
Et pourquoi la conversion de fonction en pointeur est effectuée pour check<void(*)()>(fun);
, car dans déduction d'argument de modèle ,
Avant le début de la déduction, les ajustements suivants à [~ # ~] p [~ # ~] et [~ # ~] un [~ # ~] sont créés:
1) Si [~ # ~] p [~ # ~] n'est pas un type de référence,
- si [~ # ~] a [~ # ~] est un type de tableau, ...;
- sinon, si [~ # ~] a [~ # ~] est un type de fonction, [~ # ~ ] a [~ # ~] est remplacé par le type de pointeur obtenu à partir de la conversion de fonction en pointeur;
check()
prend le paramètre par valeur, puis la conversion fonction-pointeur est effectuée et le type déduit de T
sera également le pointeur de fonction, c'est-à-dire void(*)()
.
Lorsque vous utilisez un nom de fonction comme expression, il se désintègre vers un pointeur sur lui-même. Donc fun
sera le même que &fun
.
Quant à la chose typeid
, de cette référence :
Les conversions Lvalue-to-rvalue, array-to-pointer ou function-to-pointer ne sont pas effectuées.
[Je souligne]