web-dev-qa-db-fra.com

Différence de type entre "fun" et "& fun"?

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, typeids renvoie des résultats différents:

FvvE
PFvvE

Pourquoi donc?

30
NPS

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);

compilateur en ligne

28
VTT

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(*)().

17
songyuanyao

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]

6