Extending the namespace
std
Содержание |
Добавление объявлений в
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 .
|
(since C++11) |
|
(до C++17) |
Объявлять полную или частичную специализацию любого шаблона класса-члена стандартной библиотеки или шаблона класса является неопределенным поведением.
|
Этот раздел не завершён
Причина: мини-пример |
Шаблоны функций и функции-члены шаблонов
|
Разрешено добавлять специализации шаблонов для любой стандартной библиотечной шаблонной функции в пространство имён
|
(until 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 |
пользователи могли специализировать отдельные члены или шаблоны членов
без специализации всего класса стандартной библиотеки или шаблона класса |
поведение является
неопределённым в этом случае |