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

Examine le type déclaré d'une entité ou le type et la catégorie de valeur d'une expression.

Table des matières

Syntaxe

decltype ( entité ) (1)
decltype ( expression ) (2)

Explication

1) Si l'argument est une id-expression non parenthésée ou une expression d'accès membre de classe non parenthésée, alors decltype donne le type de l' entité nommée par cette expression. S'il n'existe pas une telle entité, ou si l'argument désigne un ensemble de fonctions surchargées, le programme est mal formé.

Si l'argument est une id-expression non parenthésée désignant une liaison structurée , alors decltype donne le type référencé (décrit dans la spécification de la déclaration de liaison structurée).

(depuis C++17)

Si l'argument est une id-expression non parenthésée désignant un paramètre de template constant , alors decltype donne le type du paramètre de template (après avoir effectué toute déduction de type nécessaire si le paramètre de template est déclaré avec un type placeholder). Le type est non-const même si l'entité est un objet paramètre de template (qui est un objet const).

(depuis C++20)
2) Si l'argument est toute autre expression de type T , et
a) si la catégorie de valeur de expression est xvalue , alors decltype donne T && ;
b) si la catégorie de valeur de expression est lvalue , alors decltype donne T & ;
c) si la catégorie de valeur de expression est prvalue , alors decltype donne T .

Si expression est un appel de fonction qui retourne un prvalue de type classe ou est une expression virgule dont l'opérande droit est un tel appel de fonction, un objet temporaire n'est pas introduit pour ce prvalue.

(jusqu'à C++17)

Si expression est un prvalue autre qu'une invocation immédiate (éventuellement entre parenthèses) (depuis C++20) , un objet temporaire n'est pas matérialisé à partir de ce prvalue : un tel prvalue n'a pas d'objet résultat.

(depuis C++17)
Comme aucun objet temporaire n'est créé, le type n'a pas besoin d'être complet ou d'avoir un destructeur disponible, et peut être abstrait . Cette règle ne s'applique pas aux sous-expressions : dans decltype ( f ( g ( ) ) ) , g ( ) doit avoir un type complet, mais f ( ) n'en a pas besoin.

Notez que si le nom d'un objet est entre parenthèses, il est traité comme une expression lvalue ordinaire, ainsi decltype ( x ) et decltype ( ( x ) ) sont souvent des types différents.

decltype est utile pour déclarer des types difficiles ou impossibles à déclarer en utilisant la notation standard, comme les types liés aux lambdas ou les types dépendant de paramètres de template.

Notes

Macro de test de fonctionnalité Valeur Std Fonctionnalité
__cpp_decltype 200707L (C++11) decltype

Mots-clés

decltype

Exemple

#include <cassert>
#include <iostream>
#include <type_traits>
struct A { double x; };
const A* a;
decltype(a->x) y;       // type de y est double (type déclaré)
decltype((a->x)) z = y; // type de z est const double& (expression lvalue)
template<typename T, typename U>
auto add(T t, U u) -> decltype(t + u) // le type de retour dépend des paramètres du template
                                      // le type de retour peut être déduit depuis 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*)>,
    "Retourner auto seul ne permet pas un transfert parfait.");
decltype(auto) getRefFwdGood(const int* p) { return getRef(p); }
static_assert(std::is_same_v<decltype(getRefFwdGood), const int&(const int*)>,
    "Retourner decltype(auto) permet un transfert parfait du type de retour.");
// Alternative :
auto getRefFwdGood1(const int* p) -> decltype(getRef(p)) { return getRef(p); }
static_assert(std::is_same_v<decltype(getRefFwdGood1), const int&(const int*)>,
    "Retourner decltype(expression de retour) permet également un transfert parfait du type de retour.");
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)>,
        "Le type d'une fonction lambda est unique et sans nom");
    decltype(f) g = f;
    std::cout << f(3, 3) << ' ' << g(3, 3) << '\n';
}

Sortie :

42 42

Références

Contenu étendu
  • Norme C++23 (ISO/IEC 14882:2024) :
  • 9.2.9.5 Spécificateurs Decltype [dcl.type.decltype]
  • Norme C++20 (ISO/IEC 14882:2020) :
  • 9.2.8.4 Spécificateurs Decltype [dcl.type.decltype]
  • Norme C++17 (ISO/IEC 14882:2017) :
  • TBD Spécificateurs Decltype [dcl.type.decltype]
  • Norme C++14 (ISO/IEC 14882:2014) :
  • TBD Spécificateurs Decltype [dcl.type.decltype]
  • Norme C++11 (ISO/IEC 14882:2011) :
  • TBD Spécificateurs Decltype [dcl.type.decltype]

Voir aussi

auto spécificateur (C++11) spécifie un type déduit d'une expression
(C++11)
obtient une référence à un objet du type template pour utilisation dans un contexte non évalué
(modèle de fonction)
(C++11)
vérifie si deux types sont identiques
(modèle de classe)
Documentation C pour typeof