Namespaces
Variants

std:: declval

From cppreference.net
Utilities library
Definiert im Header <utility>
template < class T >
typename std:: add_rvalue_reference < T > :: type declval ( ) noexcept ;
(seit C++11)
(bis C++14)
(nur nicht-ausgewertet)
template < class T >
std:: add_rvalue_reference_t < T > declval ( ) noexcept ;
(seit C++14)
(nur nicht-ausgewertet)

Hilfsvorlage zum Schreiben von Ausdrücken, die in nicht-ausgewerteten Kontexten erscheinen, typischerweise der Operand von decltype . In nicht-ausgewertetem Kontext konvertiert diese Hilfsvorlage jeden Typ T (der ein unvollständiger Typ sein kann) in einen Ausdruck dieses Typs, wodurch es möglich wird, Memberfunktionen von T zu verwenden, ohne Konstruktoren durchlaufen zu müssen.

std::declval kann nur in nicht ausgewerteten Kontexten verwendet werden und muss nicht definiert werden; es ist ein Fehler, einen Ausdruck auszuwerten, der diese Funktion enthält. Formal ist das Programm fehlerhaft, wenn diese Funktion ODR-used wird.

Inhaltsverzeichnis

Parameter

(keine)

Rückgabewert

Kann nicht ausgewertet werden und gibt daher niemals einen Wert zurück. Der Rückgabetyp ist T&& (Referenzkollapsregeln finden Anwendung), es sei denn T ist (möglicherweise cv-qualifiziert) void , in welchem Fall der Rückgabetyp T ist.

Hinweise

std::declval wird häufig in Templates verwendet, wenn akzeptable Template-Parameter keinen gemeinsamen Konstruktor haben können, aber dieselbe Member-Funktion besitzen, deren Rückgabetyp benötigt wird.

Mögliche Implementierung

template<typename T>
typename std::add_rvalue_reference<T>::type declval() noexcept
{
    static_assert(false, "declval nicht erlaubt in einem ausgewerteten Kontext");
}

Beispiel

#include <iostream>
#include <utility>
struct Default
{
    int foo() const { return 1; }
};
struct NonDefault
{
    NonDefault() = delete;
    int foo() const { return 1; }
};
int main()
{
    decltype(Default().foo())               n1 = 1;     // Typ von n1 ist int
    decltype(std::declval<Default>().foo()) n2 = 1;     // gleich
//  decltype(NonDefault().foo())               n3 = n1; // Fehler: kein Standardkonstruktor
    decltype(std::declval<NonDefault>().foo()) n3 = n1; // Typ von n3 ist int
    std::cout << "n1 = " << n1 << '\n'
              << "n2 = " << n2 << '\n'
              << "n3 = " << n3 << '\n';
}

Ausgabe:

n1 = 1
n2 = 1
n3 = 1

Siehe auch

decltype Spezifizierer (C++11) ermittelt den Typ eines Ausdrucks oder einer Entität
(C++11) (entfernt in C++20) (C++17)
leitet den Ergebnistyp des Aufrufs eines aufrufbaren Objekts mit einer Reihe von Argumenten ab
(Klassentemplate)