Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
El decltype especificador de tipo produce el tipo de una expresión especificada. El decltype especificador de tipos, junto con la auto palabra clave , es útil principalmente para los desarrolladores que escriben bibliotecas de plantillas. Use auto y decltype para declarar una plantilla de función cuyo tipo de valor devuelto dependa de los tipos de sus argumentos de plantilla. O bien, use auto y decltype para declarar una plantilla de función que encapsula una llamada a otra función y, a continuación, devuelva el tipo de valor devuelto de la función ajustada.
Sintaxis
decltype(expression)
Parámetros
expression
Expresión. Para obtener más información, vea expresiones de .
Valor devuelto
Tipo del expression parámetro.
Observaciones
El decltype especificador de tipos se admite en Visual Studio 2010 o versiones posteriores y se puede usar con código nativo o administrado.
decltype(auto) (C++14) se admite en Visual Studio 2015 y versiones posteriores.
El compilador usa las siguientes reglas para determinar el tipo del expression parámetro .
Si el
expressionparámetro es un identificador o un acceso de miembro de clase,decltype(expression)es el tipo de la entidad denominada porexpression. Si no hay ninguna entidad de este tipo o elexpressionparámetro asigna un nombre a un conjunto de funciones sobrecargadas, el compilador genera un mensaje de error.Si el
expressionparámetro es una llamada a una función o a una función de operador sobrecargada,decltype(expression)es el tipo de valor devuelto de la función. Se omiten los paréntesis alrededor de un operador sobrecargado.Si el
expressionparámetro es un valor r,decltype(expression)es el tipo deexpression. Si elexpressionparámetro es un valor lvalue,decltype(expression)es una referencia lvalue al tipo deexpression.
En el ejemplo de código siguiente se muestran algunos usos del decltype especificador de tipos. En primer lugar, supongamos que ha codificado las siguientes instrucciones.
int var;
const int&& fx();
struct A { double x; };
const A* a = new A();
A continuación, examine los tipos devueltos por las cuatro decltype instrucciones de la tabla siguiente.
| Declaración | Tipo | Notas |
|---|---|---|
decltype(fx()); |
const int&& |
Referencia de rvalue a .const int |
decltype(var); |
int |
Tipo de variable var. |
decltype(a->x); |
double |
Tipo del acceso de miembro. |
decltype((a->x)); |
const double& |
Los paréntesis internos hacen que la instrucción se evalúe como una expresión en lugar de un acceso de miembro. Y como a se declara como puntero const , el tipo es una referencia a const double. |
decltype y auto
En C++14, puede usar decltype(auto) sin ningún tipo de valor devuelto final para declarar una plantilla de función cuyo tipo de valor devuelto depende de los tipos de sus argumentos de plantilla.
En C++11, puede usar el decltype especificador de tipo en un tipo de valor devuelto final, junto con la auto palabra clave , para declarar una plantilla de función cuyo tipo de valor devuelto depende de los tipos de sus argumentos de plantilla. Por ejemplo, considere el siguiente ejemplo de código en el que el tipo de valor devuelto de la plantilla de función depende de los tipos de los argumentos de plantilla. En el ejemplo de código, el UNKNOWN marcador de posición indica que no se puede especificar el tipo de valor devuelto.
template<typename T, typename U>
UNKNOWN func(T&& t, U&& u){ return t + u; }
La introducción del decltype especificador de tipos permite al desarrollador obtener el tipo de la expresión que devuelve la plantilla de función. Use la sintaxis de declaración de función alternativa que se muestra más adelante, la auto palabra clave y el especificador de decltype tipo para declarar un tipo de valor devuelto especificado en tiempo de ejecución . El tipo de valor devuelto especificado en tiempo de espera se determina cuando se compila la declaración, en lugar de cuando se codifica.
En el prototipo siguiente se muestra la sintaxis de una declaración de función alternativa. Los const calificadores y volatile y la especificación de throwexcepción son opcionales . El function_body marcador de posición representa una instrucción compuesta que especifica lo que hace la función. Como procedimiento recomendado de codificación, el expression marcador de posición de la decltype instrucción debe coincidir con la expresión especificada por la instrucción , si existe return , en function_body.
auto
function_name
(
parameters
optar)constoptarvolatileoptar->decltype(expression)noexceptoptar{function_body};
En el ejemplo de código siguiente, el tipo de valor devuelto especificado en tiempo de ejecución de la myFunc plantilla de función viene determinado por los tipos de los t argumentos de plantilla y u . Como procedimiento recomendado de codificación, el ejemplo de código también usa referencias rvalue y la plantilla de función, que admiten el forwardreenvío perfecto. Para obtener más información, vea Rvalue reference declarator: &&.
//C++11
template<typename T, typename U>
auto myFunc(T&& t, U&& u) -> decltype (forward<T>(t) + forward<U>(u))
{ return forward<T>(t) + forward<U>(u); }
//C++14
template<typename T, typename U>
decltype(auto) myFunc(T&& t, U&& u)
{ return forward<T>(t) + forward<U>(u); }
decltype funciones de reenvío y reenvío (C++11)
Las funciones de reenvío encapsulan llamadas a otras funciones. Considere una plantilla de función que reenvía sus argumentos o los resultados de una expresión que implique esos argumentos a otra función. Además, la función de reenvío devuelve el resultado de llamar a la otra función. En este escenario, el tipo de valor devuelto de la función de reenvío debe ser el mismo que el tipo de valor devuelto de la función ajustada.
En este escenario, no se puede escribir una expresión de tipo adecuada sin el especificador de decltype tipos. El decltype especificador de tipos habilita las funciones de reenvío genérico porque no pierde la información necesaria sobre si una función devuelve un tipo de referencia. Para obtener un ejemplo de código de una función de reenvío, consulte el ejemplo de plantilla de función anterior myFunc .
Ejemplos
En el ejemplo de código siguiente se declara el tipo de valor devuelto especificado en tiempo de ejecución de la plantilla Plus()de función . La Plus función procesa sus dos operandos con la operator+ sobrecarga. Por lo tanto, la interpretación del operador más (+) y el tipo de valor devuelto de la Plus función depende de los tipos de los argumentos de función.
// decltype_1.cpp
// compile with: cl /EHsc decltype_1.cpp
#include <iostream>
#include <string>
#include <utility>
#include <iomanip>
using namespace std;
template<typename T1, typename T2>
auto Plus(T1&& t1, T2&& t2) ->
decltype(forward<T1>(t1) + forward<T2>(t2))
{
return forward<T1>(t1) + forward<T2>(t2);
}
class X
{
friend X operator+(const X& x1, const X& x2)
{
return X(x1.m_data + x2.m_data);
}
public:
X(int data) : m_data(data) {}
int Dump() const { return m_data;}
private:
int m_data;
};
int main()
{
// Integer
int i = 4;
cout <<
"Plus(i, 9) = " <<
Plus(i, 9) << endl;
// Floating point
float dx = 4.0;
float dy = 9.5;
cout <<
setprecision(3) <<
"Plus(dx, dy) = " <<
Plus(dx, dy) << endl;
// String
string hello = "Hello, ";
string world = "world!";
cout << Plus(hello, world) << endl;
// Custom type
X x1(20);
X x2(22);
X x3 = Plus(x1, x2);
cout <<
"x3.Dump() = " <<
x3.Dump() << endl;
}
Plus(i, 9) = 13
Plus(dx, dy) = 13.5
Hello, world!
x3.Dump() = 42
Visual Studio 2017 y versiones posteriores: El compilador analiza los argumentos decltype cuando se declaran las plantillas en lugar de crear instancias. Por lo tanto, si se encuentra una especialización no dependiente en el decltype argumento , no se aplazará al tiempo de creación de instancias; se procesará inmediatamente y se diagnosticarán los errores resultantes en ese momento.
En el ejemplo siguiente se muestra este error del compilador que se genera en el punto de declaración:
#include <utility>
template <class T, class ReturnT, class... ArgsT> class IsCallable
{
public:
struct BadType {};
template <class U>
static decltype(std::declval<T>()(std::declval<ArgsT>()...)) Test(int); //C2064. Should be declval<U>
template <class U>
static BadType Test(...);
static constexpr bool value = std::is_convertible<decltype(Test<T>(0)), ReturnT>::value;
};
constexpr bool test1 = IsCallable<int(), int>::value;
static_assert(test1, "PASS1");
constexpr bool test2 = !IsCallable<int*, int>::value;
static_assert(test2, "PASS2");
Requisitos
Visual Studio 2010 o versiones posteriores.
decltype(auto) requiere Visual Studio 2015 o posterior.