Especificador decltype
Inspecciona el tipo declarado de una entidad o el tipo y la categoría de valor de una expresión.
Contenido |
[editar]Sintaxis
decltype ( entidad) | (1) | (desde C++11) | |||||||
decltype ( expresión) | (2) | (desde C++11) | |||||||
[editar]Explicación
decltype
produce el tipo de la entidad denominada por esta expresión. Si no existe tal entidad, o si el argumento denomina un conjunto de funciones sobrecargadas, el programa está mal formado. Si el argumento es una expresión-id sin paréntesis que denomina un vínculo estructurado, entonces | (desde C++17) |
Si el argumento es una expresión-id sin paréntesis que denomina un parámetro de plantilla sin tipo, entonces | (desde C++20) |
T
, y:decltype
produce T. Si la expresión es una llamada a función que devuelve un pr-valor de tipo de clase o es una expresión coma cuyo operando derecho es tal llamada a función, no se introduce un objeto temporal para ese pr-valor. | (hasta C++17) |
Si la expresión es un pr-valor distinto de una ({posiblemente entre paréntesis) invocación inmediata(desde C++20), no se materializa un objeto temporal no se de ese pr-valor: dicho pr-valor no tiene un objeto resultado. | (desde C++17) |
Ten en cuenta que si el nombre de un objeto está entre paréntesis, se trata como una expresión l-valor ordinaria, por lo tanto, decltype(x) y decltype((x)) a menudo son tipos diferentes.
decltype
es útil al declarar tipos que son difíciles o imposibles de declarar usando la notación estándar, como los tipos relacionados con lambdas o los tipos que dependen de los parámetros de plantilla.
[editar]Notas
Macro de prueba de característica | Valor | Estándar | Comentario |
---|---|---|---|
__cpp_decltype | 200707L | (C++11) | decltype |
[editar]Palabras clave
[editar]Ejemplo
#include <iostream>#include <type_traits> struct A {double x;};const A* a; decltype(a->x) y;// el tipo de y es double (tipo declarado) decltype((a->x)) z = y;// el tipo de z es const double& (expresión l-valor) template<typename T, typename U>auto add(T t, U u)-> decltype(t + u)// tipo de retorno depende de los parámetros de plantilla// tipo de retorno puede deducirse desde C++14{return t + u;} constint& getRef(constint* p){return*p;} static_assert(std::is_same_v<decltype(getRef), constint&(constint*)>);auto getRefFwdBad(constint* p){return getRef(p);} static_assert(std::is_same_v<decltype(getRefFwdBad), int(constint*)>, "Simplemente devolver auto no es reenvío perfecto."); decltype(auto) getRefFwdGood(constint* p){return getRef(p);} static_assert(std::is_same_v<decltype(getRefFwdGood), constint&(constint*)>, "Devolver decltype(auto) reenvía perfectamente el tipo de retorno."); // De manera alterna:auto getRefFwdGood1(constint* p)-> decltype(getRef(p)){return getRef(p);} static_assert(std::is_same_v<decltype(getRefFwdGood1), constint&(constint*)>, "Devolver decltype(expresión return) también reenvía perfectamente el tipo de retorno."); int main(){int i =33; decltype(i) j = i *2; std::cout<<"i y j son el mismo tipo? "<<std::boolalpha<<std::is_same_v<decltype(i), decltype(j)><<'\n'; std::cout<<"i = "<< i <<", "<<"j = "<< j <<'\n'; auto f =[](int a, int b)->int{return a * b;}; decltype(f) g = f;// el tipo de una función lambda es único y sin nombre i = f(2, 2); j = g(3, 3); std::cout<<"i = "<< i <<", "<<"j = "<< j <<'\n';}
Salida:
i y j son el mismo tipo? true i = 33, j = 66 i = 4, j = 9
[editar]Véase también
Especificador auto | Especifica un tipo definido por una expresión. (C++11) |
(C++11) | Obtiene el tipo de expresión de un contexto no evaluado. (plantilla de función) |
(C++11) | Comprueba si dos tipos son los mismos (plantilla de clase) |