Freigeben über


decltype-Typspezifizierer

Der decltype-Typspezifizierer ergibt den Typ eines angegebenen Ausdrucks. decltype 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 Vorlagenfunktion zu deklarieren, deren Rückgabetyp von den Typen seiner Vorlagenargumente abhängt. Oder Sie verwenden auto und decltype, um eine Vorlagenfunktion zu deklarieren, die einen Aufruf einer anderen Funktion umschließt und anschließend den Rückgabetyp der umschlossenen Funktion zurückgibt.

 decltype( expression )

Parameter

Parameter

Beschreibung

expression

Ein Ausdruck. Weitere Informationen finden Sie unter Ausdrücke (C++).

Rückgabewert

Der Typ des expression-Parameters.

Hinweise

Der Typspezifizierer decltype wird in Visual C++ 2010 oder höher unterstützt und kann mit systemeigenem oder verwaltetem Code verwendet werden.

Der Compiler bestimmt mithilfe der folgenden Regeln den Typ des expression-Parameters.

  • Wenn der expression-Parameter ein Bezeichner oder ein Klassenmemberzugriff ist, ist decltype(expression) der Typ der durch expression benannten Entität. Wenn keine solche Entität vorhanden ist oder der expression-Parameter einen Satz überladener Funktionen bezeichnet, erzeugt der Compiler eine Fehlermeldung.

  • Wenn der expression-Parameter ein Aufruf einer Funktion oder überladenen Operatorfunktion ist, ist decltype(expression) der Rückgabetyp der Funktion. Klammern um einen überladenen Operator werden ignoriert.

  • Wenn der expression-Parameter ein rvalue ist, ist decltype(expression) der Typ von expression. Wenn der expression-Parameter ein lvalue ist, ist decltype(expression) ein lvalue-Verweis auf den Typ von expression.

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

Typ

Hinweise

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"

Verwenden Sie den decltype-Typspezifizierer in Kombination mit dem auto-Schlüsselwort, um eine Vorlagenfunktion 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 Vorlagenfunktion 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>
UNKNOWNfunc(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 die return-Anweisung (sofern vorhanden) in function_body angegeben wird.

auto function_name(parametersopt) constopt volatileopt −> decltype(expression) throwopt {function_body};

Im folgenden Codebeispiel wird der spät angegebene Rückgabetyp der myFunc-Vorlagenfunktion 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: &&.

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); }; 

"decltyp" und Weiterleitungsfunktionen

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-Vorlagenfunktionsbeispiel.

Beispiel

Im folgenden Codebeispiel wird der spät angegebene Rückgabetyp der Plus()-Vorlagenfunktion 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: /EHsc
//
#include "stdafx.h"
#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;
}

Ausgabe

Dieses Codebeispiel führt zu folgenden Ergebnissen.

13

13.5

Hello, world!

42

Anforderungen

Visual C++ 2010 oder höhere Versionen

Siehe auch

Referenz

Einfache Typnamen