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; } const int& getRef(const int* p) { return *p; } static_assert(std::is_same_v<decltype(getRef), const int&(const int*)>); auto getRefFwdBad(const int* p) { return getRef(p); } static_assert(std::is_same_v<decltype(getRefFwdBad), int(const int*)>, "Simplemente devolver auto no es reenvío perfecto."); decltype(auto) getRefFwdGood(const int* p) { return getRef(p); } static_assert(std::is_same_v<decltype(getRefFwdGood), const int&(const int*)>, "Devolver decltype(auto) reenvía perfectamente el tipo de retorno."); // De manera alterna: auto getRefFwdGood1(const int* p) -> decltype(getRef(p)) { return getRef(p); } static_assert(std::is_same_v<decltype(getRefFwdGood1), const int&(const int*)>, "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) |