c++ c++11 conditional-operator typetraits lvalue

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 si T es válida, de lo contrario C 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 un A&&

  • common_type se especifica mediante declval , 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 produce int&& , lo cual es inesperado

  • propuesta 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 produce int