Especificador decltype
Inspecciona el tipo declarado de una entidad o el tipo y la categoría de valor de una expresión.
Sintaxis
decltype ( entidad )
|
(1) | (desde C++11) | |||||||
decltype ( expresión )
|
(2) | (desde C++11) | |||||||
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) |
decltype(f(g())), g() debe tener un tipo completo, pero f() no.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.
Notas
| Macro de prueba de característica | Valor | Estándar | Comentario |
|---|---|---|---|
__cpp_decltype |
200707L |
(C++11) | decltype
|
Palabras clave
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
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) |