Espacios de nombres
Variantes
Acciones

Especificador decltype

De cppreference.com
< cpp‎ | language
 
 
 
 

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

1) Si el argumento es una expresión-id sin paréntesis o una expresión de acceso a miembro de clase sin paréntesis, entonces 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 decltype produce el tipo referenciado (descrito en la especificación de la declaración del vínculo estructurado).

(desde C++17)

Si el argumento es una expresión-id sin paréntesis que denomina un parámetro de plantilla sin tipo, entonces decltype produce el tipo del parámetro de plantilla (después de realizar cualquier deducción de tipo necesaria si el parámetro de plantilla se declara con un tipo de marcador de posición). El tipo es no-const incluso si la entidad es un objeto de parámetro de plantilla (que es un objeto const).

(desde C++20)
2) Si el argumento es cualquier otra expresión de tipo T, y:
a) si la categoría de valor de la expresión es x-valor, entonces decltype produce T&&;
b) si la categoría de valor de la expresión es l-valor, entonces decltype produce T&;
c) si la categoría de valor de la expresión es pr-valor, entonces 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)
Debido a que no se crea un objeto temporal, el tipo no necesita estar completo o tener un destructor disponible, y puede ser abstracto. Esta regla no se aplica a las subexpresiones: en 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.

[editar] Notas

Macro de prueba de característica Valor Estándar Comentario
__cpp_decltype 200707L (C++11) decltype

[editar] Palabras clave

decltype

[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)[editar]
(C++11)
Obtiene el tipo de expresión de un contexto no evaluado.
(plantilla de función) [editar]
(C++11)
Comprueba si dos tipos son los mismos
(plantilla de clase) [editar]