Extending the namespace std

< cpp‎ | language
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Function declaration
Lambda function declaration
inline specifier
Exception specifications (until C++20)
noexcept specifier (C++11)
decltype (C++11)
auto (C++11)
alignas (C++11)
Storage duration specifiers
Alternative representations
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Attributes (C++11)
typedef declaration
Type alias declaration (C++11)
Implicit conversions - Explicit conversions
static_cast - dynamic_cast
const_cast - reinterpret_cast
Memory allocation
Class-specific function properties
Special member functions


[edit] 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};

[edit] Adding template specializations

It is allowed to add template specializations for any standard library class (since C++20)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
namespace std {
    template <> struct hash<MyType> {
      std::size_t operator()(const MyType& t) const { return t.hash(); }
  • It is undefined behavior to declare a full specialization of any member function of a standard library class template
  • It is undefined behavior to declare a full specialization of any member function template of a standard library class or class template
  • It is undefined behavior to declare a full or partial specialization of any member class template of a standard library class or class template.
  • It is undefined behavior to declare a full or partial specialization of any standard library variable template, except where explicitly allowed.
(since C++14)
  • Specializing the template std::complex for any type other than float, double, and long double is unspecified.
  • Specializations of std::hash for program-defined types must satisfy Hash requirements.
  • Specializations of std::atomic must have a deleted copy constructor, a deleted copy assignment operator, and a constexpr value constructor.
  • Specializations of std::istreambuf_iterator must have a trivial copy constructor, a constexpr default constructor, and a trivial destructor.
(since C++11)
(until C++17)
  • Specializations of std::disable_sized_sentinel, std::ranges::disable_sized_range and std::ranges::enable_view shall be usable in constant expressions and have type const bool. And
    • std::disable_sized_sentinel may be specialized for cv-unqualified non-array object types S and I at least one of which is a program-defined type.
    • std::ranges::disable_sized_range and std::ranges::enable_view may be specialized for cv-unqualified program-defined types.
(since C++20)

[edit] 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.

[edit] Other restrictions

The namespace std may not be declared as an inline namespace.

[edit] Addressable functions

The 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 the a standard library function or an instantiation of a standard library function template, unless it is designated an addressable function.

The only addressable functions in the standard library are I/O manipulators that are functions (or instantiations of function templates) taking a reference to a stream as their only argument, e.g. std::endl, std::boolalpha.

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 = &std::betaf; // by unary operator&
    auto fptr1 = std::addressof(std::betal) // by std::addressof
    auto fptr2 = std::riemann_zetaf; // by function-to-pointer implicit conversion
    auto &fref = std::riemann_zetal; // forming a reference
    auto mfptr = &std::allocator<int>::allocate; // forming a pointer to member function
(since C++20)