Namespaces
Variants

decltype specifier (since C++11)

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
const / volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

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

Inhaltsverzeichnis

Syntax

decltype ( Entität ) (1)
decltype ( Ausdruck ) (2)

Erklärung

1) Wenn das Argument ein nicht in Klammern gesetzter id-expression oder ein nicht in Klammern gesetzter class member access Ausdruck ist, dann liefert decltype den Typ der Entität , die durch diesen Ausdruck benannt wird. Falls keine solche Entität existiert oder das Argument eine Menge überladener Funktionen benennt, ist das Programm fehlerhaft.

Wenn das Argument ein nicht in Klammern gesetzter id-expression ist, der eine structured binding benennt, dann liefert decltype den referenzierten Typ (beschrieben in der Spezifikation der structured binding Deklaration).

(seit C++17)

Wenn das Argument ein nicht in Klammern gesetzter id-expression ist, der einen constant template parameter benennt, dann liefert decltype den Typ des Template-Parameters (nach Durchführung etwaiger Typableitung falls der Template-Parameter mit einem Platzhaltertyp deklariert wurde). Der Typ ist non-const selbst wenn die Entität ein Template-Parameter-Objekt (welches ein const-Objekt ist) ist.

(seit C++20)
2) Wenn das Argument ein beliebiger anderer Ausdruck vom Typ T ist, und
a) wenn die Wertkategorie des Ausdrucks ein xvalue ist, dann ergibt decltype T && ;
b) wenn der Wertkategorie des Ausdrucks ein Lvalue ist, dann ergibt decltype T & ;
c) wenn die Wertkategorie des Ausdrucks ein Prvalue ist, dann liefert decltype T .

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

(bis C++17)

Wenn expression ein Prvalue ist (außer einem (möglicherweise in Klammern gesetzten) Immediate Invocation (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 erzeugt wird, muss der Typ nicht vollständig sein oder einen verfügbaren Destruktor besitzen, und kann abstrakt sein. Diese Regel gilt nicht für Teilausdrücke: in decltype ( f ( g ( ) ) ) muss g ( ) einen vollständigen Typ haben, aber f ( ) muss dies nicht.

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

decltype ist nützlich, wenn Typen deklariert werden, die schwierig oder unmöglich mit Standardnotation zu deklarieren sind, wie lambda-bezogene Typen oder Typen, die von Template-Parametern abhängen.

Hinweise

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

Schlüsselwörter

decltype

Beispiel

#include <cassert>
#include <iostream>
#include <type_traits>
struct A { double x; };
const A* a;
decltype(a->x) y;       // Typ von y ist double (deklarierter Typ)
decltype((a->x)) z = y; // Typ von z ist const double& (Lvalue-Ausdruck)
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) // Rückgabetyp hängt von Template-Parametern ab
                                      // Rückgabetyp kann seit C++14 abgeleitet werden
{
    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*)>,
    "Nur auto zurückzugeben ist kein perfektes Forwarding.");
decltype(auto) getRefFwdGood(const int* p) { return getRef(p); }
static_assert(std::is_same_v<decltype(getRefFwdGood), const int&(const int*)>,
    "Rückgabe von decltype(auto) forwarded den Rückgabetyp perfekt.");
// Alternativ:
auto getRefFwdGood1(const int* p) -> decltype(getRef(p)) { return getRef(p); }
static_assert(std::is_same_v<decltype(getRefFwdGood1), const int&(const int*)>,
    "Rückgabe von decltype(Rückgabeausdruck) forwarded den Rückgabetyp ebenfalls perfekt.");
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)>,
        "Der Typ einer Lambda-Funktion ist eindeutig und unbenannt");
    decltype(f) g = f;
    std::cout << f(3, 3) << ' ' << g(3, 3) << '\n';
}

Ausgabe:

42 42

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]

Siehe auch

auto Spezifizierer (C++11) gibt einen aus einem Ausdruck abgeleiteten Typ an
(C++11)
erhält eine Referenz auf ein Objekt des Template-Typarguments zur Verwendung in einem nicht ausgewerteten Kontext
(Funktionstemplate)
(C++11)
prüft, ob zwei Typen identisch sind
(Klassentemplate)
C-Dokumentation für typeof