c++ - debe std:: common_type use std:: decay?
c++11 conditional-operator (1)
Dados los tipos A,B
, me preocupa la definición exacta de std::common_type<A,B>
, sin tener en cuenta el caso variadic std::common_type<A...>
para tipos arbitrarios A...
Entonces deja
using T = decltype(true ? std::declval<A>() : std::declval<B>());
using C = std::common_type<A,B>;
Ahora, de acuerdo con una serie de fuentes, he encontrado las siguientes relaciones (omitiendo typename
para brevedad):
cppreference.com :
C::type = std::decay<T>::type
cplusplus.com :
C::type = T
GCC 4.8.1
<type_traits>
implementación:C::type = std::decay<T>::type
siT
es válida, de lo contrarioC
no contiene un miembro::type
("SFINAE-friendly")<type_traits>
Clang 3.3<type_traits>
:C::type = std::remove_reference<T>::type
Considero que la versión de GCC "amigable con SFINAE" es un detalle menor, mientras que std::remove_reference
y std::decay
prácticamente solo difieren en los arreglos y funciones incorporados, más la calificación std::remove_reference
, por lo que tampoco me preocupa mucho. Así que mi pregunta es
¿Debería ser decay<T>::type
o solo T
? ¿Cuál es la razón para usar decay<T>::type
? ¿Se trata solo de representar el resultado A() + B()
por ejemplo, para expresiones aritméticas?
Por ejemplo, experimentando un poco, he encontrado que en el caso de la definición "solo T
", tenemos
common_type<int&,int&> = int&
common_type<int&,long&> = long
es decir, una referencia lvalue se mantiene si los tipos son iguales . Esto refleja el hecho de que
int a, b;
(true ? a : b) = 0;
es válido, mientras
int a;
long b;
(true ? a : b) = 0;
no es. Esta semántica de "permitir la asignación si los tipos son iguales" es exactamente lo que necesito en una aplicación, y tiendo a creer que el tipo common_type
y la decay
deben ser dos pasos independientes. ¿Debo usar mis propias definiciones?
debe std :: common_type use std :: decay?
Sí, ver open-std.org/JTC1/SC22/WG21/docs/lwg-defects.html#2141 .
Versión corta (versión larga, ver enlace arriba):
declval<A>()
devuelve unA&&
common_type
se especifica mediantedeclval
, n3337:template <class T, class U> struct common_type<T, U> { typedef decltype(true ? declval<T>() : declval<U>()) type; };
common_type<int, int>::type
por lo tanto produceint&&
, lo cual es inesperadopropuesta de resolución es agregar la
decay
template <class T, class U> struct common_type<T, U> { typedef decay_t < decltype(true ? declval<T>() : declval<U>()) > type; };
common_type<int, int>::type
ahora produceint