Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
O decltype especificador de tipo produz o tipo de uma expressão especificada. O decltype especificador de tipo, juntamente com a auto palavra-chave, é útil principalmente para desenvolvedores que escrevem 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 retorna o tipo de retorno da função encapsulada.
Sintaxe
decltype(expression)
Parâmetros
expression
Uma expressão. Para obter mais informações, consulte Expressions.
Valor de retorno
O tipo do expression parâmetro.
Observações
O decltype especificador de tipo tem suporte no Visual Studio 2010 ou versões posteriores e pode ser usado com código nativo ou gerenciado.
decltype(auto) O (C++14) tem suporte no Visual Studio 2015 e posterior.
O compilador usa as regras a seguir para determinar o tipo do expression parâmetro.
Se o
expressionparâ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 oexpressionparâmetro nomeia um conjunto de funções sobrecarregadas, o compilador produzirá uma mensagem de erro.Se o
expressionparâmetro for uma chamada para uma função ou uma função de operador sobrecarregada,decltype(expression)será o tipo de retorno da função. Parênteses em torno de um operador sobrecarregado são ignorados.Se o
expressionparâmetro for um rvalue,decltype(expression)será o tipo deexpression. Se oexpressionparâmetro for um lvalue,decltype(expression)será uma referência lvalue ao tipo deexpression.
O exemplo de código a seguir demonstra alguns usos do decltype especificador de tipo. 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 decltype instruções na tabela a seguir.
| Declaração | Tipo | Anotações |
|---|---|---|
decltype(fx()); |
const int&& |
Uma referência rvalue a um const int. |
decltype(var); |
int |
O tipo de variável var. |
decltype(a->x); |
double |
O tipo de 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 const ponteiro, o tipo é uma referência a const double. |
decltype e auto
No 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.
No 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 de modelo. No exemplo de código, o UNKNOWN espaço reservado indica que o 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 retornada pelo modelo de função. Use a sintaxe de declaração de função alternativa mostrada posteriormente, a auto palavra-chave e o especificador de decltype tipo para declarar um tipo de retorno especificado tardiamente . 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 qualificadores e 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 de codificação recomendada, o expression espaço reservado na decltype instrução deve corresponder à expressão especificada pela return instrução, se houver, no function_body.
auto
function_name
(
parameters
optar)constoptarvolatileoptar->decltype(expression)noexceptoptar{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 t argumentos e u modelo. Como uma prática de codificação recomendada, o exemplo de código também usa referências rvalue e o forward modelo de função, que dão suporte ao encaminhamento perfeito. Para obter mais informações, consulte o 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 envolva esses argumentos para outra função. Além disso, a função de encaminhamento retorna o resultado de chamar a outra função. Nesse cenário, o tipo de retorno da função de encaminhamento deve ser o mesmo que o tipo de retorno da função encapsulada.
Nesse cenário, você não pode escrever uma expressão de tipo apropriada sem o especificador de decltype 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 Plus função processa seus dois operandos com a operator+ sobrecarga. Portanto, a interpretação do operador de adição (+) e do tipo de retorno da Plus 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 decltype argumentos quando os modelos são declarados em vez de instanciados. Portanto, 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 todos os erros resultantes são diagnosticados nesse momento.
O exemplo a seguir mostra um erro desse compilador gerado no ponto 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) requer o Visual Studio 2015 ou posterior.