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

Contenidos

Agregar declaraciones a std

Es comportamiento indefinido añadir declaraciones o definiciones al espacio de nombres std o a cualquier espacio de nombres anidado dentro de std , con algunas excepciones señaladas a continuación.

#include <utility>
namespace std
{
    // una definición de función añadida al espacio de nombres std: comportamiento indefinido
    pair<int, int> operator+(pair<int, int> a, pair<int, int> b)
    {
        return {a.first + b.first, a.second + b.second};
    }
}

Agregar especializaciones de plantilla

Plantillas de clase

Se permite añadir especializaciones de plantilla para cualquier plantilla de clase de la biblioteca estándar al espacio de nombres std solo si la declaración depende de al menos un tipo definido por el programa y la especialización satisface todos los requisitos de la plantilla original, excepto donde tales especializaciones estén prohibidas.

// Obtener la declaración de la plantilla principal std::hash.
// No estamos autorizados a declararla nosotros mismos.
// <typeindex> garantiza proporcionar dicha declaración,
// y es mucho más económico de incluir que <functional>.
#include <typeindex> 
// Especializar std::hash para que MyType pueda usarse como clave en
// std::unordered_set y std::unordered_map. Abrir el espacio de nombres
// std puede introducir accidentalmente comportamiento indefinido, y no es
// necesario para especializar plantillas de clase.
template<>
struct std::hash<MyType>
{
    std::size_t operator()(const MyType& t) const { return t.hash(); }
};
  • Especializar la plantilla std::complex para cualquier tipo que no sea float , double , y long double no está especificado.
  • Las especializaciones de std::atomic deben tener un constructor de copia eliminado, un operador de asignación de copia eliminado y un constructor de valor constexpr.
  • Las especializaciones de std::istreambuf_iterator deben tener un constructor de copia trivial, un constructor por defecto constexpr y un destructor trivial.
(desde C++11)
(hasta C++17)

Es comportamiento indefinido declarar una especialización total o parcial de cualquier plantilla de clase miembro de una clase o plantilla de clase de la biblioteca estándar.

Plantillas de función y funciones miembro de plantillas

Se permite agregar especializaciones de plantilla para cualquier plantilla de función de la biblioteca estándar al espacio de nombres std solo si la declaración depende de al menos un tipo definido por el programa y la especialización satisface todos los requisitos de la plantilla original, excepto cuando dichas especializaciones estén prohibidas.

(until C++20)

Es comportamiento indefinido declarar una especialización completa de cualquier plantilla de función de la biblioteca estándar.

(since C++20)

Es comportamiento indefinido declarar una especialización completa de cualquier función miembro de una plantilla de clase de la biblioteca estándar:

Es comportamiento indefinido declarar una especialización completa de cualquier función miembro plantilla de una clase o plantilla de clase de la biblioteca estándar:

Plantillas de variables

Es comportamiento indefinido declarar una especialización total o parcial de cualquier plantilla de variable de la biblioteca estándar, excepto donde se permita explícitamente.

(desde C++20)
(desde C++14)

Instanciación explícita de plantillas

Se permite instanciar explícitamente una class (since C++20) template definida en la biblioteca estándar solo si la declaración depende del nombre de al menos un program-defined type y la instanciación cumple con los requisitos de la biblioteca estándar para el template original.

Otras restricciones

El espacio de nombres std no puede declararse como un espacio de nombres en línea .

Restricción de direccionamiento

El comportamiento de un programa C++ no está especificado (posiblemente mal formado) si intenta explícita o implícitamente formar un puntero, referencia (para funciones libres y funciones miembro estáticas) o puntero-a-miembro (para funciones miembro no estáticas) a una función de la biblioteca estándar o una instanciación de una plantilla de función de la biblioteca estándar, a menos que esté designada como una función direccionable (ver más abajo).

El siguiente código estaba bien definido en C++17, pero conduce a comportamientos no especificados y posiblemente falla al compilar desde C++20:

#include <cmath>
#include <memory>
int main()
{
    // por operador unario &
    auto fptr0 = &static_cast<float(&)(float, float)>(std::betaf);
    // por std::addressof
    auto fptr1 = std::addressof(static_cast<float(&)(float, float)>(std::betaf));
    // por conversión implícita función-a-puntero
    auto fptr2 = static_cast<float(&)(float)>(std::riemann_zetaf);
    // formando una referencia
    auto& fref = static_cast<float(&)(float)>(std::riemann_zetaf);
}

Funciones direccionables designadas

(desde C++20)

Informes de defectos

Los siguientes informes de defectos que modifican el comportamiento se aplicaron retroactivamente a los estándares de C++ publicados anteriormente.

DR Se aplica a Comportamiento publicado Comportamiento correcto
LWG 120 C++98 los usuarios podían instanciar explícitamente plantillas de la
biblioteca estándar para tipos no definidos por el usuario
prohibido
LWG 232 C++98 los usuarios podían especializar explícitamente plantillas de la biblioteca estándar
si la declaración depende de un nombre definido por el usuario con
enlace externo (que puede referirse a un tipo no definido por el usuario)
solo permitido para
tipos definidos por el usuario
LWG 422 C++98 los usuarios podían especializar miembros individuales o plantillas de miembros
sin especializar toda la clase o plantilla de clase de la biblioteca estándar
el comportamiento es
indefinido en este caso