¿Por qué remove_reference no funciona en las funciones?

38

Me encontré con algo extraño al hacer una metaprogramación de plantilla el otro día. Básicamente se trata de esta afirmación, no (como era de esperar) pasar.

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

Al principio pensé que estaba cometiendo un error sintáctico al definir una referencia de función, pero esta afirmación pasa, mostrando que ese no es el caso.

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

También intenté implementarme remove_referencecopiando la fuente de cppreference pero tampoco funcionó. ¿Que esta pasando aqui?

Artikash dice reinstalar a Mónica
fuente

Respuestas:

42

Bienvenido al mundo de los tipos de funciones abominables.

void() &es no una referencia a void(). La forma de deletrear eso sería void(&)()(que si usted remove_reference_t, volvería void(), eso remove_reference_t funciona en referencias a funciones, si lo que proporciona es en realidad una referencia al tipo de función).

A lo que void() &realmente se refiere es al tipo de una función miembro calificada como referencia después de quitar la clase. Es decir:

struct C {
    void f() &;
};

El tipo de &C::fes void (C::*)() &. Pero todos los punteros a los miembros pueden escribirse como T C::*para algún tipo T, y en este caso el tipo Tsería void() &.

Ver también P0172 .

Barry
fuente
3
Alguien debería crear una pregunta canónica para tipos de funciones abominables.
Brian
Wow, C ++ nunca deja de sorprenderme, incluso si lo he aprendido y lo he usado durante casi 10 años.
Kelvin Hu el
13

El tipo que tiene no es una referencia a una función, sino una función con un calificador de referencia .

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