Namespaces
Variants

Type

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

Objets , références , fonctions incluant les spécialisations de modèles de fonction , et expressions possèdent une propriété appelée type , qui restreint à la fois les opérations permises pour ces entités et fournit une signification sémantique aux séquences de bits autrement génériques.

Table des matières

Classification des types

Le système de types C++ comprend les types suivants :

(depuis C++11)
  • le type bool ;
  • types caractères :
  • types caractères étroits :
  • types caractères ordinaires : char , signed char , unsigned char [1]
  • le type char8_t
(depuis C++20)
  • types de caractères larges : char16_t , char32_t , (depuis C++11) wchar_t ;
  • types entiers signés :
  • types entiers signés standard : signed char , short , int , long , long long ;
  • types entiers signés étendus (définis par l'implémentation);
(depuis C++11)
  • types entiers non signés :
  • types entiers non signés standards : unsigned char , unsigned short , unsigned , unsigned long , unsigned long long ;
  • types entiers non signés étendus (chaque type correspond à un type entier signé étendu, et vice versa);
(depuis C++11)
(depuis C++23)
  • référence lvalue vers des types objet ;
  • référence lvalue vers des types fonction ;
  • référence rvalue vers des types d'objet ;
  • référence rvalue vers des types de fonction ;
(depuis C++11)
(depuis C++11)
  1. signed char et unsigned char sont des types de caractères étroits, mais ils ne sont pas des types de caractères. En d'autres termes, l'ensemble des types de caractères étroits n'est pas un sous-ensemble de l'ensemble des types de caractères.

Pour chaque type non qualifié-cv autre que référence et fonction, le système de types prend en charge trois versions supplémentaires qualifiées-cv de ce type ( const , volatile , et const volatile ).

Autres catégories

Un type d'objet (voir aussi std::is_object ) est un type (éventuellement qualifié cv) qui n'est pas un type fonction, pas un type référence, et pas un void (éventuellement qualifié cv).

Les types suivants sont collectivement appelés types scalaires (voir aussi std::is_scalar ):

(depuis C++11)
  • versions qualifiées cv de ces types

Les types suivants sont collectivement appelés types à durée de vie implicite :

Les types suivants sont collectivement appelés types trivialement copiables :

Les types suivants sont collectivement appelés types à disposition standard :

(depuis C++11)

Diagramme hiérarchique des traits de type

cpp types v3.svg

Remarque : Les éléments de l'image SVG sont cliquables, mais vous devez d'abord ouvrir le diagramme dans un nouvel onglet du navigateur

Catégories dépréciées

Les types suivants sont collectivement appelés types POD (voir aussi std::is_pod ) :

  • types scalaires
  • classes POD
  • tableaux de ces types
  • versions qualifiées cv de ces types
(obsolète en C++20)

Les types suivants sont collectivement appelés types triviaux (voir aussi std::is_trivial ) :

(depuis C++11)
(obsolète en C++26)

Type défini par le programme

Une spécialisation définie par le programme est une spécialisation explicite ou une spécialisation partielle qui ne fait pas partie de la bibliothèque standard C++ et n'est pas définie par l'implémentation.

Un type défini par le programme est l'un des types suivants :

(depuis C++11)

Nommage des types

Un nom peut être déclaré pour faire référence à un type au moyen de :

Les types qui n'ont pas de noms doivent souvent être référencés dans les programmes C++ ; la syntaxe pour cela est connue sous le nom de type-id . La syntaxe du type-id qui nomme le type T est exactement la syntaxe d'une déclaration d'une variable ou fonction de type T , avec l'identifiant omis, sauf que le decl-specifier-seq de la grammaire de déclaration est contraint à type-specifier-seq , et que de nouveaux types peuvent être définis uniquement si le type-id apparaît du côté droit d'une déclaration d'alias de type non-template.

int* p;               // déclaration d'un pointeur vers int
static_cast<int*>(p); // type-id est "int*"
int a[3];   // déclaration d'un tableau de 3 int
new int[3]; // type-id est "int[3]" (appelé new-type-id)
int (*(*x[2])())[3];      // déclaration d'un tableau de 2 pointeurs vers des fonctions
                          // retournant un pointeur vers un tableau de 3 int
new (int (*(*[2])())[3]); // type-id est "int (*(*[2])())[3]"
void f(int);                    // déclaration d'une fonction prenant int et retournant void
std::function<void(int)> x = f; // paramètre de type template est un type-id "void(int)"
std::function<auto(int) -> void> y = f; // identique
std::vector<int> v;       // déclaration d'un vecteur de int
sizeof(std::vector<int>); // type-id est "std::vector<int>"
struct { int x; } b;         // crée un nouveau type et déclare un objet b de ce type
sizeof(struct { int x; });   // erreur : impossible de définir de nouveaux types dans une expression sizeof
using t = struct { int x; }; // crée un nouveau type et déclare t comme alias de ce type
sizeof(static int); // erreur : spécificateurs de classe de stockage ne font pas partie de type-specifier-seq
std::function<inline void(int)> f; // erreur : les spécificateurs de fonction non plus

La partie déclarateur de la grammaire de déclaration avec le nom supprimé est appelée abstract-declarator .

Type-id peut être utilisé dans les situations suivantes :

(jusqu'à C++17)

Le type-id peut être utilisé avec certaines modifications dans les situations suivantes :

  • dans la liste des paramètres d'une fonction (lorsque le nom du paramètre est omis), le type-id utilise decl-specifier-seq au lieu de type-specifier-seq (en particulier, certains spécificateurs de classe de stockage sont autorisés) ;
  • dans le nom d'une fonction de conversion définie par l'utilisateur , le déclarateur abstrait ne peut pas inclure d'opérateurs de fonction ou de tableau.

Spécificateur de type élaboré

Les spécificateurs de type élaborés peuvent être utilisés pour faire référence à un nom de classe précédemment déclaré (classe, struct ou union) ou à un nom d'énumération précédemment déclaré, même si le nom était masqué par une déclaration de non-type . Ils peuvent également être utilisés pour déclarer de nouveaux noms de classe.

Voir elaborated type specifier pour plus de détails.

Type statique

Le type d'une expression qui résulte de l'analyse à la compilation du programme est connu comme le static type de l'expression. Le static type ne change pas pendant l'exécution du programme.

Type dynamique

Si une expression glvalue fait référence à un objet polymorphe , le type de son objet le plus dérivé est appelé le type dynamique.

// donné
struct B { virtual ~B() {} }; // polymorphic type
struct D : B {};               // polymorphic type
D d; // objet le plus dérivé
B* ptr = &d;
// le type statique de (*ptr) est B
// le type dynamique de (*ptr) est D

Pour les expressions prvalue, le type dynamique est toujours identique au type statique.

Type incomplet

Les types suivants sont des types incomplets :

Tous les autres types sont complets.

L'un des contextes suivants exige que le type T soit complet :

(En général, lorsque la taille et la disposition de T doivent être connues.)

Si l'une de ces situations se produit dans une unité de traduction, la définition du type doit apparaître dans la même unité de traduction. Sinon, elle n'est pas requise.

Un type d'objet incomplètement défini peut être complété :

  • Un type de classe (tel que class X ) peut être considéré comme incomplet à un moment donné dans une unité de traduction et considéré comme complet ultérieurement ; le type class X est le même type aux deux moments :
struct X;            // déclaration de X, aucune définition fournie pour l'instant
extern X* xp;        // xp est un pointeur vers un type incomplet :
                     // la définition de X n'est pas accessible
void foo()
{
    xp++;            // incorrect : X est incomplet
}
struct X { int i; }; // définition de X
X x;                 // OK : la définition de X est accessible
void bar()
{
    xp = &x;         // OK : le type est « pointeur vers X »
    xp++;            // OK : X est complet
}
  • Le type déclaré d'un objet tableau peut être un tableau de type classe incomplet et donc incomplet ; si le type classe est complété ultérieurement dans l'unité de traduction, le type tableau devient complet ; le type tableau à ces deux points est le même type.
  • Le type déclaré d'un objet tableau peut être un tableau de taille inconnue et donc être incomplet à un moment donné dans une unité de traduction et complet ultérieurement ; les types tableau à ces deux points ("tableau de taille inconnue de T " et "tableau de N T ") sont des types différents.

Le type d'un pointeur ou d'une référence vers un tableau de taille inconnue pointe ou réfère définitivement vers un type incomplet. Un tableau de taille inconnue désigné par une typedef déclaration réfère définitivement à un type incomplet. Dans les deux cas, le type tableau ne peut être complété :

extern int arr[];   // le type de arr est incomplet
typedef int UNKA[]; // UNKA est un type incomplet
UNKA* arrp;         // arrp est un pointeur vers un type incomplet
UNKA** arrpp;
void foo()
{
    arrp++;         // erreur : UNKA est un type incomplet
    arrpp++;        // OK : sizeof UNKA* est connu
}
int arr[10];        // maintenant le type de arr est complet
void bar()
{
    arrp = &arr;    // OK : conversion de qualification (depuis C++20)
    arrp++;         // erreur : UNKA ne peut pas être complété
}

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement publié Comportement corrigé
CWG 328 C++98 les membres de classe de type incomplet n'étaient pas interdits
si un objet du type classe n'était jamais créé
les membres de données non statiques de classe
doivent être complets
CWG 977 C++98 le moment où un type énumération devient
complet dans sa définition n'était pas clair
le type est complet une fois que le
type sous-jacent est déterminé
CWG 1362 C++98 les conversions définies par l'utilisateur vers le type T* ou T& exigeaient T d'être complet non requis
CWG 2006 C++98 les types void qualifiés cv étaient des types objet et des types complets exclus des deux catégories
CWG 2448 C++98 seuls les types non qualifiés cv pouvaient être des types entiers et à virgule flottante autorise les types qualifiés cv
CWG 2630 C++98 il n'était pas clair si une classe est considérée comme complète en dehors
de l'unité de traduction où la définition de la classe apparaît
la classe est complète
si sa définition est
accessible dans ce cas
CWG 2643 C++98 le type d'un pointeur vers un tableau de taille inconnue
ne pouvait pas être complété (mais il est déjà complet)
le type de tableau pointé
ne peut pas être complété
LWG 2139 C++98 la signification de "type défini par l'utilisateur" n'était pas claire définit et utilise "type
défini par le programme" à la place
LWG 3119 C++11 il n'était pas clair si les types de fermeture sont des types définis par le programme clarifié

Références

  • Norme C++23 (ISO/CEI 14882:2024) :
  • 6.8.2 Types fondamentaux [basic.fundamental]
  • Norme C++20 (ISO/CEI 14882:2020) :
  • 6.8.2 Types fondamentaux [basic.fundamental]
  • Norme C++17 (ISO/CEI 14882:2017) :
  • 6.9.1 Types fondamentaux [basic.fundamental]
  • Norme C++14 (ISO/CEI 14882:2014) :
  • 3.9.1 Types fondamentaux [basic.fundamental]
  • Norme C++11 (ISO/CEI 14882:2011) :
  • 3.9.1 Types fondamentaux [basic.fundamental]
  • Norme C++98 (ISO/CEI 14882:1998) :
  • 3.9.1 Types fondamentaux [basic.fundamental]

Voir aussi

Type traits Interfaces basées sur des templates à la compilation pour interroger les propriétés des types

Liens externes

1. Arborescence des types C++0x de Howard Hinnant