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

Содержание

Добавление объявлений в std

Это неопределённое поведение — добавлять объявления или определения в пространство имён std или в любое пространство имён, вложенное в std , за несколькими исключениями, указанными ниже.

#include <utility>
namespace std
{
    // определение функции, добавленное в пространство имен std: неопределенное поведение
    pair<int, int> operator+(pair<int, int> a, pair<int, int> b)
    {
        return {a.first + b.first, a.second + b.second};
    }
}

Добавление специализаций шаблонов

Шаблоны классов

Разрешено добавлять специализации шаблонов для любых стандартных библиотечных шаблонов классов в пространство имён std только если объявление зависит по крайней мере от одного програмно-определённого типа и специализация удовлетворяет всем требованиям исходного шаблона, за исключением случаев, когда такие специализации запрещены.

// Получаем объявление основного шаблона std::hash.
// Нам не разрешено объявлять его самостоятельно.
// <typeindex> гарантированно предоставляет такое объявление,
// и его подключение значительно дешевле, чем <functional>.
#include <typeindex> 
// Специализируем std::hash, чтобы MyType можно было использовать как ключ в
// std::unordered_set и std::unordered_map. Открытие пространства имен
// std может случайно привести к неопределенному поведению и не является
// необходимым для специализации шаблонов классов.
template<>
struct std::hash<MyType>
{
    std::size_t operator()(const MyType& t) const { return t.hash(); }
};
  • Специализация шаблона std::complex для любых типов, кроме float , double и long double не определена.
  • Специализации std::numeric_limits должны определять все члены, объявленные static const (until C++11) static constexpr (since C++11) в основной шаблон, таким образом, чтобы они могли использоваться как integral constant expressions .
  • Специализации std::hash для програмно-определённых типов должны удовлетворять Hash требованиям.
  • Специализации std::atomic должны иметь удалённый конструктор копирования, удалённый оператор присваивания копированием и constexpr конструктор по умолчанию.
  • Специализации std::istreambuf_iterator должны иметь тривиальный конструктор копирования, constexpr конструктор по умолчанию и тривиальный деструктор.
(since C++11)
(до C++17)

Объявлять полную или частичную специализацию любого шаблона класса-члена стандартной библиотеки или шаблона класса является неопределенным поведением.

Шаблоны функций и функции-члены шаблонов

Разрешено добавлять специализации шаблонов для любой стандартной библиотечной шаблонной функции в пространство имён std только если объявление зависит по крайней мере от одного програмно-определённого типа и специализация удовлетворяет всем требованиям оригинального шаблона, за исключением случаев, когда такие специализации запрещены.

(until C++20)

Объявление полной специализации любой стандартной библиотечной шаблонной функции является неопределённым поведением.

(since C++20)

Объявлять полную специализацию любой функции-члена шаблона класса стандартной библиотеки является неопределённым поведением:

Объявлять полную специализацию любой шаблонной функции-члена класса или шаблона класса стандартной библиотеки является неопределенным поведением:

Шаблоны переменных

Объявление полной или частичной специализации любого шаблона переменной стандартной библиотеки является неопределенным поведением, за исключением случаев, когда это явно разрешено.

(since C++20)
(since C++14)

Явное инстанцирование шаблонов

Разрешено явно инстанцировать шаблон класса (начиная с C++20) определённый в стандартной библиотеке только в том случае, если объявление зависит от имени по крайней мере одного программо-определённого типа и инстанцирование удовлетворяет требованиям стандартной библиотеки к исходному шаблону.

Другие ограничения

Пространство имен std не может быть объявлено как встроенное пространство имен .

Ограничение на взятие адреса

Поведение программы на C++ не определено (возможно, некорректно), если она явно или неявно пытается сформировать указатель, ссылку (для свободных функций и статических функций-членов) или указатель на член (для нестатических функций-членов) на функцию стандартной библиотеки или инстанцирование шаблона функции стандартной библиотеки, за исключением случаев, когда она обозначена как адресуемая функция (см. ниже).

Следующий код был корректным в C++17, но приводит к неопределённому поведению и возможным ошибкам компиляции начиная с C++20:

#include <cmath>
#include <memory>
int main()
{
    // через унарный operator&
    auto fptr0 = &static_cast<float(&)(float, float)>(std::betaf);
    // через std::addressof
    auto fptr1 = std::addressof(static_cast<float(&)(float, float)>(std::betaf));
    // через неявное преобразование функции в указатель
    auto fptr2 = static_cast<float(&)(float)>(std::riemann_zetaf);
    // формирование ссылки
    auto& fref = static_cast<float(&)(float)>(std::riemann_zetaf);
}

Назначенные адресуемые функции

(начиная с C++20)

Отчеты о дефектах

Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены задним числом к ранее опубликованным стандартам C++.

DR Applied to Behavior as published Correct behavior
LWG 120 C++98 пользователи могли явно инстанцировать шаблоны
стандартной библиотеки для неопределённых пользователем типов
запрещено
LWG 232 C++98 пользователи могли явно специализировать шаблоны стандартной библиотеки
если объявление зависит от определённого пользователем имени
с внешней линковкой (которое может ссылаться на неопределённый пользователем тип)
разрешено только для
определённых пользователем типов
LWG 422 C++98 пользователи могли специализировать отдельные члены или шаблоны членов
без специализации всего класса стандартной библиотеки или шаблона класса
поведение является
неопределённым в этом случае