Extending the namespace std
Adding declarations to std
It is undefined behavior to add declarations or definitions to namespace std
or to any namespace nested within std
, with a few exceptions noted below.
#include <utility> namespace std { // a function definition added to namespace std: undefined behavior pair<int, int> operator+(pair<int, int> a, pair<int, int> b) { return {a.first + b.first, a.second + b.second}; } }
Adding template specializations
Class templates
It is allowed to add template specializations for any standard library class template to the namespace std
only if the declaration depends on at least one program-defined type and the specialization satisfies all requirements for the original template, except where such specializations are prohibited.
// Get the declaration of the primary std::hash template. // We are not permitted to declare it ourselves. // <typeindex> is guaranteed to provide such a declaration, // and is much cheaper to include than <functional>. #include <typeindex> // Specialize std::hash so that MyType can be used as a key in // std::unordered_set and std::unordered_map. Opening namespace // std can accidentally introduce undefined behavior, and is not // necessary for specializing class templates. template<> struct std::hash<MyType> { std::size_t operator()(const MyType& t) const { return t.hash(); } };
- Specializing the template std::complex for any type other than float, double, and long double is unspecified.
- Specializations of std::numeric_limits must define all members declared
static const
(until C++11)static constexpr
(since C++11) in the primary template, in such a way that they are usable as integral constant expressions.
|
(since C++11) |
|
(until C++17) |
It is undefined behavior to declare a full or partial specialization of any member class template of a standard library class or class template.
This section is incomplete Reason: mini-example |
Function templates and member functions of templates
It is allowed to add template specializations for any standard library function template to the namespace |
(until C++20) |
It is undefined behavior to declare a full specialization of any standard library function template. |
(since C++20) |
This section is incomplete Reason: mini-example |
It is undefined behavior to declare a full specialization of any member function of a standard library class template:
This section is incomplete Reason: mini-example |
It is undefined behavior to declare a full specialization of any member function template of a standard library class or class template:
This section is incomplete Reason: mini-example |
Variable templates
It is undefined behavior to declare a full or partial specialization of any standard library variable template, except where explicitly allowed.
|
(since C++14) |
|
(since C++20) |
Explicit instantiation of templates
It is allowed to explicitly instantiate a class (since C++20)template defined in the standard library only if the declaration depends on the name of at least one program-defined type and the instantiation meets the standard library requirements for the original template.
This section is incomplete Reason: mini-example |
Program-defined types
Program-defined specializations are explicit template specializations or partial specializations that are not part of the C++ standard library and not defined by the implementation.
Program-defined types are non-closure class types or enumeration types that are not part of the C++ standard library and not defined by the implementation, or closure type of non-implementation-provided lambda expressions (since C++11), or instantiation of program-defined specializations.
Other restrictions
The namespace std
may not be declared as an inline namespace.
Addressing restrictionThe behavior of a C++ program is unspecified (possibly ill-formed) if it explicitly or implicitly attempts to form a pointer, reference (for free functions and static member functions) or pointer-to-member (for non-static member functions) to a standard library function or an instantiation of a standard library function template, unless it is designated an addressable function (see below). Following code was well-defined in C++17, but leads to unspecified behaviors and possibly fails to compile since C++20: #include <cmath> #include <memory> int main() { auto fptr0 = &static_cast<float(&)(float, float)>(std::betaf); // by unary operator& auto fptr1 = std::addressof(static_cast<float(&)(float, float)>(std::betaf)); // by std::addressof auto fptr2 = static_cast<float(&)(float)>(std::riemann_zetaf); // by function-to-pointer implicit conversion auto& fref = static_cast<float(&)(float)>(std::riemann_zetaf); // forming a reference } Designated addressable functions
|
(since C++20) |
Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
LWG 120 | C++98 | users could explicitly instantiate standard library templates for non-user defined types | prohibited |
LWG 232 | C++98 | users could explicitly specialize standard library templates if the declaration depends on a user-defined name of external linkage (which can refer to a non-user-defined type) |
only allowed for user-defined types |
LWG 422 | C++98 | users could specialize individual members or member templates without specializing the whole standard library class or class template |
the behavior is undefined |