Namespaces
Variants

Extending the namespace std

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

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::atomic doivent avoir un constructeur de copie supprimé, un opérateur d'affectation de copie supprimé et un constructeur de valeur constexpr.
  • Les spécialisations de std::istreambuf_iterator doivent avoir un constructeur de copie trivial, un constructeur par défaut constexpr et un destructeur trivial.
(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.

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

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

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 :

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 :

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++20)
(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.

Autres restrictions

L'espace de noms std ne peut pas être déclaré comme un espace de noms en ligne .

Restriction d'adressage

Le 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