Diferencia entre std::decay y std::remove_reference
Cuando hago metaprogramación de plantillas en C++, a menudo me encuentro con algo como lo siguiente:
template <typename T>
S<T> make_wrapper(T&& t) { return S<T>(std::forward<T>(t)); }
Sé que debería usar algo como std::decay
el tipo de devolución, pero ¿por qué no std::remove_reference
funcionaría tan bien? ¿Cuál es la diferencia aquí? Qué pasa std::remove_cvref
?
Considere por ejemplo
#include <type_traits>
int main()
{
static_assert(std::is_same_v<
std::decay_t<const int&>,
std::remove_reference_t<const int&>
>); // int != const int
}
std::decay
eliminará cualquier calificador cv, remove_reference
no lo hará. Simplemente eliminará la parte de "referencia" del tipo.
De la referencia :
Aplica conversiones implícitas de valor a valor, matriz a puntero y función a puntero al tipo T, elimina calificadores cv y define el tipo resultante como el tipo de miembro typedef.
Por lo tanto, std::decay
realizará muchas más conversiones de tipos que std::remove_reference
.
También hay más modificadores de tipo para aplicaciones más matizadas que solo realizarán partes seleccionadas del conjunto de transformaciones posibles decay
, como remove_cv
, remove_volatile
o, en C++20, remove_cvref
.