decltype
(C++)
L'identificatore decltype
di tipo restituisce il tipo di un'espressione specificata. L'identificatore decltype
di tipo, insieme alla auto
parola chiave , è utile principalmente per gli sviluppatori che scrivono librerie di modelli. Usare auto
e decltype
per dichiarare un modello di funzione il cui tipo restituito dipende dai tipi degli argomenti del modello. In alternativa, usare auto
e decltype
per dichiarare un modello di funzione che esegue il wrapping di una chiamata a un'altra funzione e quindi restituisce il tipo restituito della funzione di cui è stato eseguito il wrapping.
Sintassi
decltype(
expression
)
Parametri
expression
Espressione. Per altre informazioni, vedere Espressioni.
Valore restituito
Tipo del parametro expression
.
Osservazioni:
L'identificatore decltype
di tipo è supportato in Visual Studio 2010 o versioni successive e può essere usato con codice nativo o gestito. decltype(auto)
(C++14) è supportato in Visual Studio 2015 e versioni successive.
Il compilatore usa le regole seguenti per determinare il tipo del expression
parametro .
Se il
expression
parametro è un identificatore o un accesso membro di classe,decltype(expression)
è il tipo dell'entità denominata daexpression
. Se non esiste un'entità di questo tipo o ilexpression
nome di un set di funzioni di overload, il compilatore restituisce un messaggio di errore.Se il
expression
parametro è una chiamata a una funzione o a una funzione operatore di overload,decltype(expression)
è il tipo restituito della funzione. Le parentesi di un operatore di overload vengono ignorate.Se il
expression
parametro è un rvalue,decltype(expression)
è il tipo diexpression
. Se ilexpression
parametro è un lvalue,decltype(expression)
è un riferimento lvalue al tipo diexpression
.
Nell'esempio di codice seguente vengono illustrati alcuni usi dell'identificatore decltype
di tipo . In primo luogo, si supponga di aver codificato le istruzioni seguenti.
int var;
const int&& fx();
struct A { double x; };
const A* a = new A();
Esaminare quindi i tipi restituiti dalle quattro decltype
istruzioni nella tabella seguente.
decltype
e auto
In C++14 è possibile usare decltype(auto)
senza tipo restituito finale per dichiarare un modello di funzione il cui tipo restituito dipende dai tipi degli argomenti del modello.
In C++11 è possibile usare l'identificatore decltype
di tipo in un tipo restituito finale, insieme auto
alla parola chiave , per dichiarare un modello di funzione il cui tipo restituito dipende dai tipi degli argomenti del modello. Si consideri ad esempio l'esempio di codice seguente in cui il tipo restituito del modello di funzione dipende dai tipi degli argomenti del modello. Nell'esempio di codice il UNKNOWN
segnaposto indica che non è possibile specificare il tipo restituito.
template<typename T, typename U>
UNKNOWN func(T&& t, U&& u){ return t + u; };
L'introduzione dell'identificatore decltype
di tipo consente a uno sviluppatore di ottenere il tipo dell'espressione restituita dal modello di funzione. Usare la sintassi di dichiarazione di funzione alternativa visualizzata in un secondo momento, la auto
parola chiave e l'identificatore decltype
di tipo per dichiarare un tipo restituito specificato in ritardo. Il tipo restituito specificato in ritardo viene determinato quando la dichiarazione viene compilata, anziché quando viene codificata.
Il prototipo indicato di seguito mostra la sintassi per la dichiarazione di una funzione alternativa. I const
qualificatori e volatile
e la specifica dell'eccezione throw
sono facoltativi. Il function_body
segnaposto rappresenta un'istruzione composta che specifica le operazioni eseguite dalla funzione. Come procedura consigliata per la codifica, il expression
segnaposto nell'istruzione decltype
deve corrispondere all'espressione specificata dall'istruzione return
, se presente, in function_body
.
auto
function_name
(
parameters
volatile
opt)
const
opt opt ->
decltype(
expression
)
noexcept
{
function_body
};
Nell'esempio di codice seguente il tipo restituito specificato in ritardo del myFunc
modello di funzione è determinato dai tipi degli argomenti del t
modello e u
. Come procedura consigliata per la codifica, l'esempio di codice usa anche riferimenti rvalue e il forward
modello di funzione, che supportano l'inoltro perfetto. Per altre informazioni, vedere Dichiaratore di riferimento 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
funzioni di inoltro e (C++11)
Le funzioni di inoltro eseguono il wrapping delle chiamate ad altre funzioni. Si pensi a un modello di funzione che inoltra i relativi argomenti o i risultati di un'espressione che include tali argomenti, a un'altra funzione. Inoltre, la funzione di inoltro restituisce il risultato della chiamata all'altra funzione. In questo scenario il tipo restituito della funzione di inoltro deve essere uguale al tipo restituito della funzione di cui è stato eseguito il wrapping.
In questo scenario non è possibile scrivere un'espressione di tipo appropriata senza l'identificatore di decltype
tipo. L'identificatore decltype
di tipo abilita funzioni di inoltro generico perché non perde le informazioni necessarie sull'eventuale restituzione di un tipo riferimento da parte di una funzione. Per un esempio di codice di una funzione di inoltro, vedere l'esempio di modello di funzione precedente myFunc
.
Esempi
Nell'esempio di codice seguente viene dichiarato il tipo restituito specificato in ritardo del modello Plus()
di funzione . La Plus
funzione elabora i due operandi con l'overload operator+
. L'interpretazione dell'operatore più (+
) e il tipo restituito della Plus
funzione dipendono quindi dai tipi degli argomenti della funzione.
// 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 versioni successive: il compilatore analizza gli decltype
argomenti quando i modelli vengono dichiarati anziché creare istanze. Pertanto, se nell'argomento decltype
viene trovata una specializzazione non dipendente, non verrà posticipata al tempo di creazione di istanze, viene elaborata immediatamente e gli eventuali errori risultanti vengono diagnosticati in quel momento.
Nell'esempio seguente viene illustrato questo tipo di errore del compilatore che viene generato al momento della dichiarazione:
#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");
Requisiti
Visual Studio 2010 o versioni successive.
decltype(auto)
richiede Visual Studio 2015 o versione successiva.
Commenti e suggerimenti
https://aka.ms/ContentUserFeedback.
Presto disponibile: Nel corso del 2024 verranno gradualmente disattivati i problemi di GitHub come meccanismo di feedback per il contenuto e ciò verrà sostituito con un nuovo sistema di feedback. Per altre informazioni, vedereInvia e visualizza il feedback per