Extending the namespace
std
Table des matières |
Ajout de déclarations à
std
Il est un comportement indéfini d'ajouter des déclarations ou des définitions à l'espace de noms
std
ou à tout espace de noms imbriqué dans
std
, à quelques exceptions notées ci-dessous.
#include <utility> namespace std { // une définition de fonction ajoutée à l'espace de noms std : comportement indéfini pair<int, int> operator+(pair<int, int> a, pair<int, int> b) { return {a.first + b.first, a.second + b.second}; } }
Ajout de spécialisations de modèles
Modèles de classe
Il est permis d'ajouter des spécialisations de modèles pour toute classe modèle de la bibliothèque standard dans l'espace de noms
std
uniquement si la déclaration dépend d'au moins un
type défini par le programme
et que la spécialisation satisfait à toutes les exigences du modèle original, sauf lorsque de telles spécialisations sont interdites.
// Obtenir la déclaration du modèle principal de std::hash. // Nous ne sommes pas autorisés à le déclarer nous-mêmes. // <typeindex> garantit de fournir une telle déclaration, // et est beaucoup moins coûteux à inclure que <functional>. #include <typeindex> // Spécialiser std::hash pour que MyType puisse être utilisé comme clé dans // std::unordered_set et std::unordered_map. L'ouverture de l'espace de noms // std peut introduire accidentellement un comportement indéfini, et n'est pas // nécessaire pour spécialiser les modèles de classe. template<> struct std::hash<MyType> { std::size_t operator()(const MyType& t) const { return t.hash(); } };
- Spécialiser le modèle std::complex pour tout type autre que float , double , et long double n'est pas spécifié.
- Les spécialisations de std::numeric_limits doivent définir tous les membres déclarés static const (jusqu'en C++11) static constexpr (depuis C++11) dans le modèle principal, de telle manière qu'ils soient utilisables comme expressions constantes entières .
|
(depuis C++11) |
|
(jusqu'à C++17) |
Il est un comportement indéfini de déclarer une spécialisation complète ou partielle de toute classe membre template d'une classe ou classe template de la bibliothèque standard.
|
Cette section est incomplète
Raison : mini-exemple |
Modèles de fonction et fonctions membres de modèles
|
Il est permis d'ajouter des spécialisations de modèle pour toute fonction modèle de la bibliothèque standard dans l'espace de noms
|
(jusqu'en C++20) |
|
Déclarer une spécialisation complète de toute fonction modèle de la bibliothèque standard est un comportement non défini. |
(depuis C++20) |
|
Cette section est incomplète
Raison : mini-exemple |
Il est un comportement indéfini de déclarer une spécialisation complète de toute fonction membre d'un modèle de classe de la bibliothèque standard :
|
Cette section est incomplète
Raison : mini-exemple |
Il est un comportement indéfini de déclarer une spécialisation complète de toute fonction membre template d'une classe ou classe template de la bibliothèque standard :
|
Cette section est incomplète
Raison : mini-exemple |
Modèles de variables
|
Il s'agit d'un comportement indéfini de déclarer une spécialisation totale ou partielle de tout modèle de variable de la bibliothèque standard, sauf autorisation explicite.
|
(depuis C++14) |
Instanciation explicite des templates
Il est permis d'instancier explicitement un modèle de classe (depuis C++20) défini dans la bibliothèque standard uniquement si la déclaration dépend du nom d'au moins un type défini par le programme et que l'instanciation satisfait aux exigences de la bibliothèque standard pour le modèle original.
|
Cette section est incomplète
Raison : mini-exemple |
Autres restrictions
L'espace de noms
std
ne peut pas être déclaré comme un
espace de noms en ligne
.
Restriction d'adressageLe comportement d'un programme C++ est non spécifié (éventuellement mal formé) s'il tente explicitement ou implicitement de former un pointeur, une référence (pour les fonctions libres et les fonctions membres statiques) ou un pointeur-vers-membre (pour les fonctions membres non statiques) vers une fonction de la bibliothèque standard ou une instanciation d'un modèle de fonction de la bibliothèque standard, sauf si elle est désignée comme une fonction adressable (voir ci-dessous). Le code suivant était bien défini en C++17, mais conduit à des comportements non spécifiés et peut échouer à compiler depuis C++20 : #include <cmath> #include <memory> int main() { // par opérateur unaire & auto fptr0 = &static_cast<float(&)(float, float)>(std::betaf); // par std::addressof auto fptr1 = std::addressof(static_cast<float(&)(float, float)>(std::betaf)); // par conversion implicite fonction-vers-pointeur auto fptr2 = static_cast<float(&)(float)>(std::riemann_zetaf); // formation d'une référence auto& fref = static_cast<float(&)(float)>(std::riemann_zetaf); } Fonctions adressables désignées
|
(depuis C++20) |
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 | Applicable à | Comportement publié | Comportement corrigé |
|---|---|---|---|
| LWG 120 | C++98 |
les utilisateurs pouvaient instancier explicitement des modèles
de la bibliothèque standard pour des types non-définis par l'utilisateur |
interdit |
| LWG 232 | C++98 |
les utilisateurs pouvaient spécialiser explicitement des modèles de la bibliothèque standard
si la déclaration dépend d'un nom défini par l'utilisateur ayant une liaison externe (qui peut référencer un type non-défini par l'utilisateur) |
uniquement autorisé pour
les types définis par l'utilisateur |
| LWG 422 | C++98 |
les utilisateurs pouvaient spécialiser des membres individuels ou des modèles de membres
sans spécialiser toute la classe ou le modèle de classe de la bibliothèque standard |
le comportement est
indéfini dans ce cas |