typeid c++
std:: common_type con referencias a type_info (1)
Estoy perplejo: al actualizar a GCC 6 (RC1), algunos códigos de plantillas que utilizan std::common_type
que funcionaron antes fallaron. Lo intenté en Clang, y eso también falla ... ¡así que debo estar haciendo algo mal!
El código equivale a:
#include <type_traits>
#include <typeinfo>
using namespace std;
// common_type of two const type_info& is ok (compiles ok)
common_type<const type_info&, const type_info&>::type func1();
// common_type of three type_info& is bad...(fails to compile)
common_type<const type_info&, const type_info&, const type_info&>::type func2();
// common_type of two const int& is ok
common_type<const int&, const int&>::type func3();
// common_type of three const int& is ok too!
common_type<const int&, const int&, const int&>::type func4();
El segundo common_type
con tres parámetros de tipo std::type_info const &
falla en compilar. clang cryptically sugiere que use un std::common_type
dos argumentos, pero esto es en una expansión de plantilla donde no puedo controlar las entradas.
Esto parece muy extraño: ¿por qué const type_info&
case con 3 pero ningún otro tipo de tipo aparentemente equivalente fallaría?
Consulte aquí: https://godbolt.org/g/Ob4y0x
Primero, common_type_t<T1, T2>
es (aproximadamente) std::decay_t<decltype(true? std::declval<T1>() : std::declval<T2>())>
. Disminuye el tipo: elimina la referencia, elimina la calificación CV de nivel superior y realiza la conversión de matriz a puntero y de función a puntero.
Entonces, common_type<const type_info&, const type_info&>::type
es type_info
. Si func1
la declaración de func1
parece funcionar, tendrá graves problemas al escribir su definición.
common_type_t<T1, T2, T3>
es common_type_t<common_type_t<T1, T2>, T3>
, por common_type<const type_info&, const type_info&, const type_info&>::type
tanto common_type<const type_info&, const type_info&, const type_info&>::type
is common_type<type_info, const type_info&>::type
.
Esto da como resultado una expresión ternaria de categoría de valor mixto, que según las reglas en [expr.cond] intentará hacer que un type_info
temporal salga del operando elegido, que no funciona porque se type_info
el constructor de copia de type_info
.
En implementaciones amigables con SFINAE, esto resulta en un tipo common_type<const type_info&, const type_info&, const type_info&>
que no tiene ningún type
miembro. Si utiliza una implementación no compatible con SFINAE, obtendrá un error difícil en su lugar.