Namensräume
Varianten
Aktionen

decltype-Spezifizierer (seit C++11)

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

Untersucht den deklarierten Typ einer Entität oder den Typ und die Wertkategorie eines Ausdrucks.

Inhalt

[bearbeiten] Syntax

decltype ( entity ) (1)
decltype ( expression ) (2)

[bearbeiten] Erklärung

1) Wenn das Argument ein nicht in Klammern gesetzter id-Ausdruck oder ein nicht in Klammern gesetzter Klassenmitgliedszugriffs-Ausdruck ist, liefert decltype den Typ der durch diesen Ausdruck benannten Entität. Gibt es keine solche Entität oder benennt das Argument eine Menge überladener Funktionen, ist das Programm fehlerhaft.

Wenn das Argument ein nicht in Klammern gesetzter id-Ausdruck ist, der eine strukturierte Bindung benennt, liefert decltype den *Referenztyp* (beschrieben in der Spezifikation der strukturierten Bindungsdeklaration).

(seit C++17)

Wenn das Argument ein nicht in Klammern gesetzter id-Ausdruck ist, der einen Nicht-Typ-Vorlagenparameter benennt, liefert decltype den Typ des Vorlagenparameters (nach Durchführung einer notwendigen Typableitung, falls der Vorlagenparameter mit einem Platzhaltertyp deklariert wurde). Der Typ ist nicht const, auch wenn die Entität ein Vorlagenparameterobjekt ist (was ein const-Objekt ist).

(seit C++20)
2) Wenn das Argument ein beliebiger anderer Ausdruck vom Typ T ist, und
a) wenn die Wertkategorie von expression ein xvalue ist, liefert decltype T&&;
b) wenn die Wertkategorie von expression ein lvalue ist, liefert decltype T&;
c) wenn die Wertkategorie von expression ein prvalue ist, liefert decltype T.

Wenn expression ein Funktionsaufruf ist, der einen prvalue vom Klassentyp zurückgibt, oder ein Komma-Ausdruck, dessen rechtes Operand ein solcher Funktionsaufruf ist, wird für diesen prvalue kein temporäres Objekt eingeführt.

(bis C++17)

Wenn expression ein prvalue ist außer einem (möglicherweise in Klammern gesetzten) sofortigen Aufruf(seit C++20), wird kein temporäres Objekt aus diesem prvalue materialisiert: ein solcher prvalue hat kein Ergebnisobjekt.

(seit C++17)
Da kein temporäres Objekt erstellt wird, muss der Typ nicht vollständig sein oder einen verfügbaren Destruktor haben und kann abstrakt sein. Diese Regel gilt nicht für Unterausdrücke: in decltype(f(g())) muss g() einen vollständigen Typ haben, aber f() muss es nicht.

Beachten Sie, dass, wenn der Name eines Objekts in Klammern gesetzt ist, er als gewöhnlicher lvalue-Ausdruck behandelt wird, sodass decltype(x) und decltype((x)) oft unterschiedliche Typen sind.

decltype ist nützlich, wenn Typen deklariert werden, die mit Standardnotationen schwierig oder unmöglich zu deklarieren sind, wie z. B. Lambda-bezogene Typen oder Typen, die von Vorlagenparametern abhängen.

[bearbeiten] Hinweise

Feature-Testmakro Wert Std Feature
__cpp_decltype 200707L (C++11) decltype

[bearbeiten] Schlüsselwörter

decltype

[bearbeiten] Beispiel

#include <cassert>
#include <iostream>
#include <type_traits>
 
struct A { double x; };
const A* a;
 
decltype(a->x) y;       // type of y is double (declared type)
decltype((a->x)) z = y; // type of z is const double& (lvalue expression)
 
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) // return type depends on template parameters
                                      // return type can be deduced since C++14
{
    return t + u;
}
 
const int& getRef(const int* p) { return *p; }
static_assert(std::is_same_v<decltype(getRef), const int&(const int*)>);
auto getRefFwdBad(const int* p) { return getRef(p); }
static_assert(std::is_same_v<decltype(getRefFwdBad), int(const int*)>,
    "Just returning auto isn't perfect forwarding.");
decltype(auto) getRefFwdGood(const int* p) { return getRef(p); }
static_assert(std::is_same_v<decltype(getRefFwdGood), const int&(const int*)>,
    "Returning decltype(auto) perfectly forwards the return type.");
 
// Alternatively:
auto getRefFwdGood1(const int* p) -> decltype(getRef(p)) { return getRef(p); }
static_assert(std::is_same_v<decltype(getRefFwdGood1), const int&(const int*)>,
    "Returning decltype(return expression) also perfectly forwards the return type.");
 
int main()
{
    int i = 33;
    decltype(i) j = i * 2;
    static_assert(std::is_same_v<decltype(i), decltype(j)>);
    assert(i == 33 && 66 == j);
 
    auto f = [i](int av, int bv) -> int { return av * bv + i; };
    auto h = [i](int av, int bv) -> int { return av * bv + i; };
    static_assert(!std::is_same_v<decltype(f), decltype(h)>,
        "The type of a lambda function is unique and unnamed");
 
    decltype(f) g = f;
    std::cout << f(3, 3) << ' ' << g(3, 3) << '\n';
}

Ausgabe

42 42

[bearbeiten] Referenzen

Erweiterter Inhalt
  • C++23 Standard (ISO/IEC 14882:2024)
  • 9.2.9.5 Decltype-Spezifizierer [dcl.type.decltype]
  • C++20 Standard (ISO/IEC 14882:2020)
  • 9.2.8.4 Decltype-Spezifizierer [dcl.type.decltype]
  • C++17 Standard (ISO/IEC 14882:2017)
  • TBD Decltype-Spezifizierer [dcl.type.decltype]
  • C++14 Standard (ISO/IEC 14882:2014)
  • TBD Decltype-Spezifizierer [dcl.type.decltype]
  • C++11 Standard (ISO/IEC 14882:2011)
  • TBD Decltype-Spezifizierer [dcl.type.decltype]

[bearbeiten] Siehe auch

auto-Spezifizierer (C++11) spezifiziert einen Typ, der aus einem Ausdruck abgeleitet wird [bearbeiten]
(C++11)
erhält eine Referenz auf ein Objekt des Typ-Template-Arguments zur Verwendung in einem nicht-ausgewerteten Kontext
(Funktionsvorlage) [edit]
(C++11)
prüft, ob zwei Typen gleich sind
(Klassenvorlage) [bearbeiten]
C-Dokumentation für typeof