cppreference - graphics c++ library
¿Qué es std:: decay y cuándo debe usarse? (2)
Cuando se trata de funciones de plantilla que toman parámetros de un tipo de plantilla, a menudo tiene parámetros universales. Los parámetros universales son casi siempre referencias de un tipo u otro. También están calificados con volatilidad constante. Como tal, la mayoría de los rasgos tipográficos no funcionan en ellos como cabría esperar:
template<class T>
void func(T&& param) {
if (std::is_same<T,int>::value)
std::cout << "param is an int/n";
else
std::cout << "param is not an int/n";
}
int main() {
int three = 3;
func(three); //prints "param is not an int"!!!!
}
http://coliru.stacked-crooked.com/a/24476e60bd906bed
La solución aquí es usar
std::decay
:
template<class T>
void func(T&& param) {
if (std::is_same<typename std::decay<T>::type,int>::value)
std::cout << "param is an int/n";
else
std::cout << "param is not an int/n";
}
¿Cuáles son las razones de la existencia de
std::decay
?
¿En qué situaciones es útil
std::decay
?
<joke> Obviamente se usa para descomponer los tipos radiactivos
std::atomic
en no radiactivos. </joke>
N2609
es el documento que propuso
std::decay
.
El artículo explica:
En pocas palabras,
decay<T>::type
es la transformación de tipo de identidad, excepto si T es un tipo de matriz o una referencia a un tipo de función. En esos casos, el tipo dedecay<T>::type
produce un puntero o un puntero a una función, respectivamente.
El ejemplo motivador es C ++ 03
std::make_pair
:
template <class T1, class T2>
inline pair<T1,T2> make_pair(T1 x, T2 y)
{
return pair<T1,T2>(x, y);
}
que aceptó sus parámetros por valor para hacer que los literales de cadena funcionen:
std::pair<std::string, int> p = make_pair("foo", 0);
Si aceptó sus parámetros por referencia, entonces
T1
se deducirá como un tipo de matriz, y luego construir un
pair<T1, T2>
estará mal formado.
Pero obviamente esto conduce a ineficiencias significativas.
De ahí la necesidad de
decay
, para aplicar el conjunto de transformaciones que ocurre cuando ocurre el paso por valor, lo que le permite obtener la eficiencia de tomar los parámetros por referencia, pero aún obtener las transformaciones de tipo necesarias para que su código funcione con literales de cadena , tipos de matriz, tipos de funciones y similares:
template <class T1, class T2>
inline pair< typename decay<T1>::type, typename decay<T2>::type >
make_pair(T1&& x, T2&& y)
{
return pair< typename decay<T1>::type,
typename decay<T2>::type >(std::forward<T1>(x),
std::forward<T2>(y));
}
Nota:
esta no es la implementación real de
make_pair
C ++ 11: el
make_pair
C ++ 11 también desenvuelve
std::reference_wrapper
s.