Perché remove_reference non funziona con le funzioni?


38

Mi sono imbattuto in qualcosa di strano quando ho fatto un modello di metaprogrammazione l'altro giorno. Fondamentalmente si riduce a questa affermazione non (come mi aspetterei) che passi.

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

All'inizio pensavo di commettere un errore sintattico nel definire un riferimento di funzione, ma questa affermazione passa, dimostrando che non è così.

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

Ho anche provato a implementarmi remove_referencecopiando l'origine da cppreference ma non ha funzionato neanche. Cosa sta succedendo qui?

Risposte:


42

Benvenuti nel mondo dei tipi di funzioni abominevoli.

void() &non è un riferimento a void(). Il modo per incantesimo che sarebbe void(&)()(che se si remove_reference_t, si dovrebbe tornare indietro void()- che remove_reference_t fa il lavoro sui riferimenti alle funzioni, se quello che si fornisce in realtà è un riferimento a tipo di funzione).

Ciò a cui void() &effettivamente fa riferimento è il tipo di una funzione membro qualificata come riferimento dopo aver rimosso la classe. Questo è:

struct C {
    void f() &;
};

Il tipo di &C::fè void (C::*)() &. Ma tutti i puntatori ai membri possono essere scritti come T C::*per qualche tipo T, e in questo caso il tipo Tsarebbe void() &.

Vedi anche P0172 .


3
Qualcuno dovrebbe creare una domanda canonica per tipi di funzioni abominevoli.
Brian,

Wow, il C ++ non manca mai di sorprendermi anche se l'ho imparato e usato da quasi 10 anni.
Kelvin Hu,

13

Il tipo si dispone non è un riferimento a una funzione, ma una funzione con un qualificatore di riferimento .

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(&)()>>);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.