c++ - Warum funktioniert remove_reference nicht bei Funktionen?




templates types (2)

Der Typ, den Sie haben, ist keine Referenz auf eine Funktion, sondern eine Funktion mit einem Referenzqualifizierer .

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

Ist neulich auf etwas Seltsames gestoßen, als ich eine Metaprogrammvorlage gemacht habe. Grundsätzlich kommt es auf diese Behauptung an, nicht (wie ich es erwarten würde) zu bestehen.

static_assert(std::is_same_v<void(), std::remove_reference_t<void()&>>);

Zuerst dachte ich, ich hätte einen syntaktischen Fehler beim Definieren einer Funktionsreferenz gemacht, aber diese Behauptung ist erfolgreich und zeigt, dass dies nicht der Fall ist.

static_assert(std::is_same_v<void()&, void()&>);

Ich habe auch versucht, remove_reference selbst zu implementieren, remove_reference ich die Quelle von cppreference kopierte, aber das hat auch nicht funktioniert. Was geht hier vor sich?


Willkommen in der Welt der abscheulichen Funktionstypen.

void() & ist kein Verweis auf void() . Die Art zu buchstabieren, die void(&)() (was, wenn Sie remove_reference_t , void() - das heißt, remove_reference_t funktioniert bei Verweisen auf Funktionen, wenn das, was Sie remove_reference_t , tatsächlich ein Verweis auf den Funktionstyp ist ).

Was void() & tatsächlich bezeichnet, ist der Typ einer referenzqualifizierten Memberfunktion, nachdem Sie die Klasse entfernt haben. Das ist:

struct C {
    void f() &;
};

Der Typ von &C::f ist void (C::*)() & . Alle Zeiger auf Mitglieder können jedoch für einen Typ T als TC::* geschrieben werden, und in diesem Fall wäre der Typ T void() & .

Siehe auch P0172 .





c++17