Extending the namespace
std
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::numeric_limits deben definir todos los miembros declarados static const (until C++11) static constexpr (since C++11) en la plantilla principal, de tal manera que sean utilizables como expresiones constantes integrales .
|
(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.
|
Esta sección está incompleta
Razón: mini-ejemplo |
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
|
(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) |
|
Esta sección está incompleta
Motivo: mini-ejemplo |
Es comportamiento indefinido declarar una especialización completa de cualquier función miembro de una plantilla de clase de la biblioteca estándar:
|
Esta sección está incompleta
Razón: mini-ejemplo |
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:
|
Esta sección está incompleta
Razón: mini-ejemplo |
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++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.
|
Esta sección está incompleta
Razón: mini-ejemplo |
Otras restricciones
El espacio de nombres
std
no puede declararse como un
espacio de nombres en línea
.
Restricción de direccionamientoEl 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 |