decltype
(C++)
Der decltype
-Typspezifizierer ergibt den Typ eines angegebenen Ausdrucks. Der decltype
-Typbezeichner ist in Kombination mit dem auto
-Schlüsselwort vor allem für Entwickler nützlich, die Vorlagenbibliotheken schreiben. Verwenden Sie auto
und decltype
, um eine Funktionsvorlage zu deklarieren, deren Rückgabetyp von den Typen seiner Vorlagenargumente abhängt. Oder Sie verwenden auto
und decltype
, um eine Funktionsvorlage zu deklarieren, die einen Aufruf einer anderen Funktion umschließt und anschließend den Rückgabetyp der umschlossenen Funktion zurückgibt.
Syntax
decltype(
expression
)
Parameter
expression
Ein Ausdruck. Weitere Informationen finden Sie unter Ausdrücke.
Rückgabewert
Der Typ des expression
-Parameters.
Hinweise
Der decltype
Typspezifizierer wird in Visual Studio 2010 oder höher 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 bestimmt mithilfe der folgenden Regeln den Typ des expression
-Parameters.
Wenn der
expression
-Parameter ein Bezeichner oder ein Klassenmemberzugriff ist, istdecltype(expression)
der Typ der durchexpression
benannten Entität. Wenn keine solche Entität vorhanden ist oder derexpression
-Parameter einen Satz überladener Funktionen bezeichnet, erzeugt der Compiler eine Fehlermeldung.Wenn der
expression
-Parameter ein Aufruf einer Funktion oder überladenen Operatorfunktion ist, istdecltype(expression)
der Rückgabetyp der Funktion. Klammern um einen überladenen Operator werden ignoriert.Wenn der
expression
-Parameter ein rvalue ist, istdecltype(expression)
der Typ vonexpression
. Wenn derexpression
-Parameter ein lvalue ist, istdecltype(expression)
ein lvalue-Verweis auf den Typ vonexpression
.
Im folgenden Codebeispiel werden einige Verwendungsmöglichkeiten des decltype
-Typspezifizierers veranschaulicht. Angenommen, Sie haben die folgenden Anweisungen codiert.
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 | type | Notizen |
---|---|---|
decltype(fx()); |
const int&& |
Ein rvalue-Verweis auf eine 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 ist, ist der Typ ein Verweis auf const double . |
decltype
und auto
Sie können decltype(auto)
ohne nachstehenden Rückgabetyp in C++14 verwenden, um eine Funktionsvorlage zu deklarieren, deren Rückgabetyp von den Typen seiner Vorlagenargumente abhängt.
In C++11 können Sie den decltype
-Typspezifizierer für einen nachstehenden Rückgabetyp in Kombination mit dem auto
-Schlüsselwort verwenden, um eine Funktionsvorlage zu deklarieren, deren Rückgabetyp von den Typen der dazugehörigen Vorlagenargumente abhängt. Betrachten Sie das folgende Codebeispiel, in dem der Rückgabetyp der Funktionsvorlage von den Typen der Vorlagenargumente abhängt. Im Codebeispiel zeigt 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
-Typspezifizierers ermöglicht es den Entwicklern, den Typ des Ausdrucks zu erhalten, den die Vorlagenfunktion zurückgibt. Verwenden Sie die alternative Funktionsdeklarationssyntax, die später angezeigt wird, das auto
-Schlüsselwort und den decltype
-Typspezifizierer, um einen spät angegebenen Rückgabetyp zu deklarieren. Der spät angegebene Rückgabetyp wird bestimmt, wenn die Deklaration kompiliert wird, anstatt wenn sie codiert wird.
Der folgende Prototyp veranschaulicht die Syntax einer alternativen Funktionsdeklaration. Beachten Sie, dass die const
- und volatile
-Qualifizierer und die throw
-Ausnahmespezifikation optional sind. Der function_body
-Platzhalter stellt eine Verbundanweisung dar, welche die Aufgabe der Funktion bezeichnet. Als empfohlene Vorgehensweise bei der Codierung soll der expression
-Platzhalter in der decltype
-Anweisung mit dem Ausdruck übereinstimmen, der durch diereturn
-Anweisung (sofern vorhanden) in function_body
angegeben wird.
auto
function_name
(
parameters
opt )
const
opt volatile
opt ->
decltype(
expression
)
noexcept
opt {
function_body
};
Im folgenden Codebeispiel wird der spät angegebene Rückgabetyp der myFunc
-Funktionsvorlage von den Typen der t
- und u
-Vorlagenargumente bestimmt. Als empfohlene Vorgehensweise bei der Codierung verwendet das Codebeispiel auch rvalue-Verweise und die forward
-Funktionsvorlage, die perfekte Weiterleitung unterstützen. Weitere Informationen finden Sie unter RValue-Verweisdeklarator: &&.
//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.
Sie können in diesem Szenario keinen geeigneten Typausdruck ohne den decltype
-Typspezifizierer schreiben. Der decltype
-Typspezifizierer aktiviert generische Weiterleitungsfunktionen, denn er verliert keine erforderlichen Informationen darüber, ob eine Funktion einen Verweistyp zurückgibt. Ein Codebeispiel für eine Weiterleitungsfunktion finden Sie im vorherigen myFunc
-Funktionsvorlagenbeispiel.
Beispiele
Im folgenden Codebeispiel wird der spät angegebene Rückgabetyp der Plus()
-Funktionsvorlage deklariert. Die Plus
-Funktion verarbeitet ihre beiden Operanden mit der operator+
-Überladung. Demzufolge hängen die Interpretation des Plus-Operators (+
) und der Rückgabetyp der Plus
-Funktion 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 eine unabhängige Spezialisierung im decltype
-Argument gefunden wird, wird sie nicht zum Zeitpunkt der Instanziierung zurückgestellt. Sie wird sofort verarbeitet, und alle resultierenden Fehler werden zu diesem Zeitpunkt untersucht.
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.
Für decltype(auto)
ist Visual Studio 2015 oder höher erforderlich.
Feedback
https://aka.ms/ContentUserFeedback.
Bald verfügbar: Im Laufe des Jahres 2024 werden wir GitHub-Tickets als Feedbackmechanismus für Inhalte auslaufen lassen und es durch ein neues Feedbacksystem ersetzen. Weitere Informationen finden Sie unter:Einreichen und Feedback anzeigen für