Ran dans quelque chose d'étrange lors de la métaprogrammation de modèle l'autre jour. Cela revient essentiellement à cette affirmation qui ne passe pas (comme je m'y attendais).
static_assert(std::is_same_v<void(), std::remove_reference_t<void()&>>);
Au début, je pensais que je faisais une erreur syntaxique en définissant une référence de fonction, mais cette assertion passe, montrant que ce n'est pas le cas.
static_assert(std::is_same_v<void()&, void()&>);
J'ai également essayé d'implémenter remove_reference
moi-même en copiant la source depuis cppreference mais cela n'a pas fonctionné non plus. Qu'est-ce qui se passe ici?
Bienvenue dans le monde des types de fonctions abominables.
void() &
n'est pas pas une référence à void()
. La façon d'épeler ce serait void(&)()
(qui si vous remove_reference_t
, Vous récupéreriez void()
- c'est-à-dire remove_reference_t
fonctionne sur les références aux fonctions, si ce que vous fournissez est en fait une référence au type de fonction).
Ce à quoi void() &
fait réellement référence est le type d'une fonction membre qualifiée de référence après avoir supprimé la classe. C'est:
struct C {
void f() &;
};
Le type de &C::f
Est void (C::*)() &
. Mais tous les pointeurs vers les membres peuvent être écrits comme T C::*
Pour certains types T
, et dans ce cas, le type T
serait void() &
.
Voir aussi P0172 .
Le type que vous avez n'est pas une référence à une fonction, mais une fonction avec un qualificatif de référence .
static_assert(std::is_same_v<void()&, void()&>);
static_assert(!std::is_same_v<void()&, void(&)()>);
static_assert(std::is_same_v<void(&)(), void(&)()>);
static_assert(std::is_same_v<void(), std::remove_reference_t<void(&)()>>);