Espacios de nombres
Variantes
Acciones

std::common_type

De cppreference.com
< cpp‎ | types
 
 
Biblioteca de servicios
 
Apoyo de tipos
Propiedades de tipos
(C++11)
(C++11)
(C++14)
(C++11)
(C++11)(hasta C++20)
(C++11)(en desuso en C++20)
(C++11)
Constantes de rasgos de tipos
Metafunciones
(C++17)
Contexto de evaluación constante
Operaciones soportadas
Relaciones y consultas de propiedades
Modificaciones de tipos
Transformaciones de tipos
(C++11)
(C++11)
(C++17)
common_type
(C++11)
(C++11)(hasta C++20)(C++17)
 
Definido en el archivo de encabezado <type_traits>
template<class... T>
struct common_type;
(desde C++11)

Determina el tipo común entre todos los tipos T..., que es el tipo al que todos los tipos T... pueden ser convertidos implícitamente. Si tal tipo existe (se determina de acuerdo a las reglas posteriores), el tipo miembro type denomina ese tipo. De lo contrario, no hay un miembro type.

  • Si sizeof...(T) es cero, no hay un miembro type.
  • Si sizeof...(T) es uno (es decir, T... contiene solo un tipo T0), el miembro type denomina el mismo tipo que std::common_type<T0, T0>::type si existe; de lo contrario, no hay un miembro type.
  • Si sizeof...(T) es dos (es decir, T... contiene exactamente dos tipos T1 y T2),
  • Si aplicar std::decay a al menos uno de T1 y T2 produce un tipo distinto, el miembro type denomina el mismo tipo que std::common_type<std::decay<T1>::type, std::decay<T2>::type>::type, si existe; si no, no hay un miembro type.
  • De lo contrario, si hay una especialización de usuario para std::common_type<T1, T2>, se usa esa especialización;
  • De lo contrario, si std::decay<decltype(false?std::declval<T1>():std::declval<T2>())>::type es un tipo válido, el miembro type denota ese tipo;
(desde C++20)
  • De lo contrario, no hay un miembro type.
  • Si sizeof...(T) es mayor que dos (es decir, T... consiste en los tipos T1, T2, R...), entonces si std::common_type<T1, T2>::type existe, el miembro type denota std::common_type<std::common_type<T1, T2>::type, R...>::type si tal tipo existe. En todos los demás casos, no hay un miembro type.

Los tipos en el paquete de parámetros T deberá cada uno ser un tipo completo, (posiblemente calificado-cv) void, o un array de límite desconocido. De lo contrario, el comportamiento está indefinido.

Si la instanciación de una plantilla anterior depende, directa o indirectamente, de un tipo incompleto, y esa instanciación podría generar un resultado distinto si ese tipo hipotéticamente se completara, el comportamiento está indefinido.

Contenido

[editar]Tipos miembro

Nombre Definición
type El tipo común para toda T...

[editar]Tipos auxiliares

template<class... T>
using common_type_t =typename common_type<T...>::type;
(desde C++14)

[editar]Especializaciones

Los usuarios pueden especializar common_type para los tipos T1 y T2 si

  • Al menos uno de T1 y T2 depende de un tipo definido por el usuario, y
  • std::decay es una transformación de identidad tanto para T1 como para T2.

Si tal especialización tiene un miembro denominado type, debe ser un tipo miembro público e inequívoco que denomina un tipo que no es una referencia sin calificadores-cv al cual tanto T1 como T2 son explícitamente convertibles. Adicionalmente, std::common_type<T1, T2>::type y std::common_type<T2, T1>::type deben denotar el mismo tipo.

Un programa que agrega especializaciones de common_type en violación de estas reglas tiene un comportamiento indefinido.

Observa que el comportamiento de un programa que agrega una especialización a cualquier otra plantilla de <type_traits> está indefinido.

La biblioteca estándar ya proporciona las siguientes especializaciones:

Especializa el rasgo std::common_type.
(especialización de plantilla de clase)[editar]
Especializa el rasgo std::common_type.
(especialización de plantilla de clase)[editar]

[editar]Posible implementación

template<typename...>using void_t =void;   // plantilla primaria (usada para cero tipos)template<class...>struct common_type {};   //////// un tipotemplate<class T>struct common_type<T>: common_type<T, T>{};   //////// dos tipostemplate<class T1, class T2>using cond_t = decltype(false?std::declval<T1>():std::declval<T2>());   template<class T1, class T2, class=void>struct common_type_2_impl {};   template<class T1, class T2>struct common_type_2_impl<T1, T2, void_t<cond_t<T1, T2>>>{using type =typenamestd::decay<cond_t<T1, T2>>::type;};   template<class T1, class T2>struct common_type<T1, T2>: common_type_2_impl<typenamestd::decay<T1>::type, typenamestd::decay<T2>::type>{};   //////// tres o más tipostemplate<class AlwaysVoid, class T1, class T2, class...R>struct common_type_multi_impl {};   template<class T1, class T2, class...R>struct common_type_multi_impl< void_t<typename common_type<T1, T2>::type>, T1, T2, R...>: common_type<typename common_type<T1, T2>::type, R...>{};     template<class T1, class T2, class... R>struct common_type<T1, T2, R...>: common_type_multi_impl<void, T1, T2, R...>{};

[editar]Notas

Para los tipos aritméticos que no están sujetos a promoción, el tipo común puede verse como el tipo de la expresión aritmética (posiblemente de modo mixto) tal que T0()+ T1()+ ... + Tn().

[editar]Ejemplo

Demuestra aritmética de modo mixto en una clase definida por el usuario

#include <iostream>#include <type_traits>   template<class T>struct Number { T n;};   template<class T, class U> Number<typename std::common_type<T, U>::type> operator+(const Number<T>& lhs, const Number<U>& rhs){return{lhs.n+ rhs.n};}   int main(){ Number<int> i1 ={1}, i2 ={2}; Number<double> d1 ={2.3}, d2 ={3.5};std::cout<<"i1i2: "<<(i1 + i2).n<<"\ni1d2: "<<(i1 + d2).n<<'\n'<<"d1i2: "<<(d1 + i2).n<<"\nd1d2: "<<(d1 + d2).n<<'\n';}

Salida:

i1i2: 3 i1d2: 4.5 d1i2: 4.3 d1d2: 5.8

[editar]Informes de defectos

Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.

ID Aplicado a Comportamiento según lo publicado Comportamiento correcto
LWG 2141 C++11 common_type<int, int>::type es int&& Tipo del resultado decae
LWG 2408 C++11 common_type no es amigable con SFINAE Se hizo amigable con SFINAE
LWG 2460 C++11 Es casi imposible escribir las especializaciones para common_type Se necesita un número reducido de especializaciones
close