Por que remove_reference não funciona em funções?


38

Ocorreu algo estranho ao fazer algum modelo de metaprogramação no outro dia. Basicamente, tudo se resume a essa afirmação que não (como eu esperaria) passar.

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

No começo, pensei que estava cometendo um erro sintático ao definir uma referência de função, mas essa afirmação passa, mostrando que esse não é o caso.

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

Também tentei remove_referenceme implementar copiando a fonte da cppreference, mas isso também não funcionou. O que está acontecendo aqui?

Respostas:


42

Bem-vindo ao mundo dos tipos de funções abomináveis.

void() &não é uma referência a void(). A maneira de se escrever isso void(&)()(que, se você remove_reference_t, você retornaria void()- ou seja remove_reference_t , funciona em referências a funções, se o que você fornecer for realmente uma referência ao tipo de função).

O que void() &realmente se refere é o tipo de uma função membro qualificada para referência depois que você tira a classe. Isso é:

struct C {
    void f() &;
};

O tipo de &C::fé void (C::*)() &. Mas todos os ponteiros para os membros podem ser escritos como T C::*para algum tipo Te, nesse caso, o tipo Tseria void() &.

Veja também P0172 .


3
Alguém deve criar uma pergunta canônica para tipos de funções abomináveis.
22719 Brian

Uau, o C ++ nunca deixa de me surpreender, mesmo que eu o tenha aprendido e usado por quase 10 anos.
Kelvin Hu

13

O tipo que você possui não é uma referência a uma função, mas uma função com um qualificador de referência .

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(&)()>>);
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.