decltype
(C++)
O especificador de tipo decltype
produz o tipo de uma expressão especificada. O especificador de tipo decltype
junto com a palavra-chave auto
, é útil principalmente para desenvolvedores que gravam bibliotecas de modelos. Use auto
e decltype
declare um modelo de função cujo tipo de retorno depende dos tipos de seus argumentos de modelo. Ou, use auto
e decltype
declare um modelo de função que encapsula uma chamada para outra função e, em seguida, retorna o tipo de retorno da função encapsulada.
Sintaxe
decltype(
expression
)
Parâmetros
expression
Uma expressão. Para obter mais informações, confira Expressões.
Valor retornado
O tipo do parâmetro expression
.
Comentários
Há suporte para o especificador de tipo decltype
no Visual Studio 2010 e em versões posteriores, e pode ser usado com código gerenciado ou nativo. Há suporte para decltype(auto)
(C++14) no Visual Studio 2015 e posterior.
O compilador usa as seguintes regras para determinar o expression
tipo do parâmetro.
Se o
expression
parâmetro for um identificador ou um acesso de membro de classe,decltype(expression)
será o tipo da entidade nomeada porexpression
. Se não houver essa entidade ou o parâmetro nomear um conjunto de funções sobrecarregadas, oexpression
compilador produzirá uma mensagem de erro.Se o parâmetro for uma chamada para uma função ou uma função de operador sobrecarregada,
decltype(expression)
é oexpression
tipo de retorno da função. Os parênteses em torno de um operador sobrecarregado são ignorados.Se o parâmetro for um rvalue,
decltype(expression)
será oexpression
tipo deexpression
. Se o parâmetro for um lvalue,decltype(expression)
será uma referência lvalue para oexpression
tipo deexpression
.
O exemplo de código a seguir demonstra alguns usos do especificador de tipo decltype
. Primeiro, suponha que você tenha codificado as instruções a seguir.
int var;
const int&& fx();
struct A { double x; };
const A* a = new A();
Em seguida, examine os tipos retornados pelas quatro instruções decltype
na tabela a seguir.
Instrução | Tipo | Observações |
---|---|---|
decltype(fx()); |
const int&& |
Uma referência rvalue para um const int . |
decltype(var); |
int |
O tipo da variável var . |
decltype(a->x); |
double |
O tipo do acesso de membro. |
decltype((a->x)); |
const double& |
Os parênteses internos fazem com que a instrução seja avaliada como uma expressão em vez de um acesso de membro. E, como a é declarado como um ponteiro const , o tipo é uma referência para const double . |
decltype
e auto
Em C++14, você pode usar decltype(auto)
sem nenhum tipo de retorno à direita para declarar um modelo de função cujo tipo de retorno depende dos tipos de seus argumentos de modelo.
Em C++11, você pode usar o decltype
especificador de tipo em um tipo de retorno à direita, juntamente com a auto
palavra-chave, para declarar um modelo de função cujo tipo de retorno depende dos tipos de seus argumentos de modelo. Por exemplo, considere o exemplo de código a seguir no qual o tipo de retorno do modelo de função depende dos tipos dos argumentos do modelo. No exemplo de código, o espaço reservado indica que o UNKNOWN
tipo de retorno não pode ser especificado.
template<typename T, typename U>
UNKNOWN func(T&& t, U&& u){ return t + u; };
A introdução do decltype
especificador de tipo permite que um desenvolvedor obtenha o tipo da expressão que o modelo de função retorna. Use a sintaxe de declaração de função alternativa, mostrada posteriormente, a palavra-chave auto
e o especificador de tipo decltype
para declarar um tipo de retorno posterior. O tipo de retorno especificado tardiamente é determinado quando a declaração é compilada, em vez de quando é codificada.
O protótipo a seguir ilustra a sintaxe de uma declaração de função alternativa. Os const
qualificadores e volatile
a especificação de throw
exceção são opcionais. O function_body
espaço reservado representa uma instrução composta que especifica o que a função faz. Como prática recomendada de codificação, o espaço reservado expression
na instrução deve corresponder à expressão especificada pela return
instrução, se houver, no function_body
.decltype
auto
function_name
(
parameters
)
const
opt optvolatile
opt opt->
decltype(
expression
)
noexcept
{
function_body
};
No exemplo de código a seguir, o tipo de retorno especificado tardiamente do myFunc
modelo de função é determinado pelos tipos dos argumentos e t
u
modelo. Como melhor prática de codificação, o exemplo de código também usa referências rvalue e o modelo de função forward
, que dá suporte para encaminhamento perfeito. Para obter mais informações, consulte Declarador de referência Rvalue: &&.
//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
e funções de encaminhamento (C++11)
As funções de encaminhamento encapsulam chamadas para outras funções. Considere um modelo de função que encaminha seus argumentos, ou os resultados de uma expressão que envolve esses argumentos, para outra função. Além disso, a função de encaminhamento retorna o resultado da chamada para a outra função. Nesse cenário, o tipo de retorno da função de encaminhamento deve ser igual ao tipo de retorno da função encapsulada.
Nesse cenário, você não pode escrever uma expressão de tipo apropriada sem o decltype
especificador de tipo. O decltype
especificador de tipo habilita funções de encaminhamento genéricas porque não perde as informações necessárias sobre se uma função retorna um tipo de referência. Para obter um exemplo de código de uma função de encaminhamento, consulte o exemplo de modelo de função anterior myFunc
.
Exemplos
O exemplo de código a seguir declara o tipo de retorno especificado tardiamente do modelo Plus()
de função . A função Plus
processa seus dois operandos com a sobrecarga operator+
. Assim, a interpretação do operador plus (+
) e do Plus
tipo de retorno da função depende dos tipos dos argumentos da função.
// 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 e posterior: O compilador analisa os argumentos decltype
quando os modelos são declarados em vez de instanciados. Assim, se uma especialização não dependente for encontrada no decltype
argumento, ela não será adiada para o tempo de instanciação, ela é processada imediatamente e quaisquer erros resultantes são diagnosticados naquele momento.
O exemplo a seguir mostra esse erro do compilador gerado no momento da declaração:
#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 ou versões posteriores.
decltype(auto)
exige o Visual Studio 2015 ou posterior.
Comentários
https://aka.ms/ContentUserFeedback.
Em breve: ao longo de 2024, vamos eliminar problemas do GitHub como o mecanismo de comentários para conteúdo e substituí-lo por um novo sistema de comentários. Para obter mais informações, consulte:Enviar e exibir comentários de