decltype
(C++)
Der decltype
Typbezeichner liefert den Typ eines angegebenen Ausdrucks. Der decltype
Typbezeichner ist zusammen mit dem auto
Schlüsselwort (keyword) in erster Linie für Entwickler nützlich, die Vorlagenbibliotheken schreiben. Verwenden und decltype
deklarieren Sie auto
eine Funktionsvorlage, deren Rückgabetyp von den Typen ihrer Vorlagenargumente abhängt. Sie können auch eine Funktionsvorlage verwenden auto
und decltype
deklarieren, die einen Aufruf einer anderen Funktion umschließt, und gibt dann den Rückgabetyp der umschlossenen Funktion zurück.
Syntax
decltype(
expression
)
Parameter
expression
Ein Ausdruck. Weitere Informationen finden Sie unter Ausdrücke.
Rückgabewert
Der Typ des expression
-Parameters.
Hinweise
Der decltype
Typbezeichner wird in Visual Studio 2010 oder höheren Versionen unterstützt und kann mit systemeigenem oder verwaltetem Code verwendet werden. decltype(auto)
(C++14) wird in Visual Studio 2015 und höher unterstützt.
Der Compiler verwendet die folgenden Regeln, um den Typ des expression
Parameters zu bestimmen.
Wenn es sich bei dem
expression
Parameter um einen Bezeichner oder einen Klassenmemembezugriff handelt,decltype(expression)
handelt es sich um den Typ der Entität, die vonexpression
. Wenn keine solche Entität vorhanden ist oder derexpression
Parameter eine Reihe überladener Funktionen benennt, liefert der Compiler eine Fehlermeldung.Wenn der
expression
Parameter ein Aufruf einer Funktion oder einer überladenen Operatorfunktion ist,decltype(expression)
ist der Rückgabetyp der Funktion. Klammern um einen überladenen Operator werden ignoriert.Wenn der
expression
Parameter ein Wert ist,decltype(expression)
ist der Typ vonexpression
. Wenn derexpression
Parameter ein lvalue ist,decltype(expression)
ist ein lvalue-Verweis auf den Typ vonexpression
.
Im folgenden Codebeispiel wird die Verwendung des decltype
Typbezeichners veranschaulicht. Gehen Sie zunächst davon aus, dass Sie die folgenden Anweisungen codiert haben.
int var;
const int&& fx();
struct A { double x; };
const A* a = new A();
Überprüfen Sie als Nächstes die Typen, die von den vier decltype
Anweisungen in der folgenden Tabelle zurückgegeben werden.
Anweisung | Typ | Notizen |
---|---|---|
decltype(fx()); |
const int&& |
Ein Rvalue-Verweis auf ein const int . |
decltype(var); |
int |
Der Typ der var -Variablen. |
decltype(a->x); |
double |
Der Typ des Memberzugriffs. |
decltype((a->x)); |
const double& |
Die innere Klammer bewirkt, dass die Anweisung als Ausdruck anstatt als Memberzugriff ausgewertet wird. Und da a als const Zeiger deklariert wird, ist der Typ ein Verweis auf const double . |
decltype
und auto
In C++14 können decltype(auto)
Sie ohne nachgestellten Rückgabetyp eine Funktionsvorlage deklarieren, deren Rückgabetyp von den Typen ihrer Vorlagenargumente abhängt.
In C++11 können Sie den decltype
Typbezeichner für einen nachfolgenden Rückgabetyp zusammen mit dem auto
Schlüsselwort (keyword) verwenden, um eine Funktionsvorlage zu deklarieren, deren Rückgabetyp von den Typen seiner Vorlagenargumente abhängt. Betrachten Sie beispielsweise das folgende Codebeispiel, in dem der Rückgabetyp der Funktionsvorlage von den Typen der Vorlagenargumente abhängt. Im Codebeispiel gibt der UNKNOWN
Platzhalter an, dass der Rückgabetyp nicht angegeben werden kann.
template<typename T, typename U>
UNKNOWN func(T&& t, U&& u){ return t + u; };
Die Einführung des decltype
Typbezeichners ermöglicht es einem Entwickler, den Typ des Ausdrucks abzurufen, den die Funktionsvorlage zurückgibt. Verwenden Sie die alternative Funktionsdeklarationssyntax, die später angezeigt wird, die auto
Schlüsselwort (keyword) und den decltype
Typbezeichner, um einen spät angegebenen Rückgabetyp zu deklarieren. Der spät angegebene Rückgabetyp wird bestimmt, wenn die Deklaration kompiliert wird und nicht, wenn sie codiert ist.
Der folgende Prototyp veranschaulicht die Syntax einer alternativen Funktionsdeklaration. Die const
Qualifizierer und volatile
die throw
Ausnahmespezifikation sind optional. Der function_body
Platzhalter stellt eine zusammengesetzte Anweisung dar, die angibt, was die Funktion bewirkt. Als bewährte Codierungspraxis sollte der expression
Platzhalter in der decltype
Anweisung mit dem ausdruck übereinstimmen, der durch die return
Anweisung (falls vorhanden) in der function_body
.
auto
function_name
(
parameters
opt)
const
opt opt->
)
expression
decltype(
noexcept
volatile
{
function_body
};
Im folgenden Codebeispiel wird der spät angegebene Rückgabetyp der myFunc
Funktionsvorlage durch die Typen der t
Argumente und u
Vorlagen bestimmt. Als bewährte Codierungspraxis verwendet das Codebeispiel auch Rvalue-Verweise und die forward
Funktionsvorlage, die die perfekte Weiterleitung unterstützen. Weitere Informationen finden Sie unter 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
und Weiterleitungsfunktionen (C++11)
Weiterleitungsfunktionen umschließen Aufrufe von anderen Funktionen. Denken Sie an eine Funktionsvorlage, die ihre Argumente oder die Ergebnisse eines Ausdrucks, der diese Argumente beinhaltet, an eine andere Funktion weiterleitet. Darüber hinaus gibt die Weiterleitungsfunktion das Ergebnis des Aufrufs der anderen Funktion zurück. In diesem Szenario muss der Rückgabetyp der Weiterleitungsfunktion mit dem Rückgabetyp der umschlossenen Funktion identisch sein.
In diesem Szenario können Sie keinen geeigneten Typausdruck ohne den decltype
Typbezeichner schreiben. Der decltype
Typbezeichner ermöglicht generische Weiterleitungsfunktionen, da keine erforderlichen Informationen darüber verloren gehen, ob eine Funktion einen Verweistyp zurückgibt. Ein Codebeispiel für eine Weiterleitungsfunktion finden Sie im beispiel der vorherigen myFunc
Funktionsvorlage.
Beispiele
Im folgenden Codebeispiel wird der spät angegebene Rückgabetyp der Funktionsvorlage Plus()
deklariert. Die Plus
Funktion verarbeitet ihre beiden Operanden mit der operator+
Überladung. Die Interpretation des Plusoperators (+
) und der Rückgabetyp der Plus
Funktion hängt also von den Typen der Funktionsargumente ab.
// 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 und höher: Der Compiler analysiert decltype
Argumente, wenn die Vorlagen deklariert und nicht instanziiert werden. Wenn also eine nicht abhängige Spezialisierung im decltype
Argument gefunden wird, wird sie nicht auf Instanziierungszeit zurückgestellt. Sie wird sofort verarbeitet, und alle resultierenden Fehler werden zu diesem Zeitpunkt diagnostiziert.
Das folgende Beispiel zeigt einen solchen Compilerfehler, der zum Zeitpunkt der Deklaration ausgelöst wird:
#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");
Anforderungen
Visual Studio 2010 oder höher.
decltype(auto)
erfordert Visual Studio 2015 oder höher.
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Issues stufenweise als Feedbackmechanismus für Inhalte abbauen und durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unterFeedback senden und anzeigen für