Расширение пространства имён 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(до C++11)static constexpr(начиная с C++11) в основном шаблоне таким образом, чтобы их можно было использовать как целочисленное константное выражение.
|
(начиная с C++11) |
|
(до C++17) |
Объявление полной или частичной специализации любого шаблонного класса-элемента стандартного библиотечного класса или шаблона класса является неопределённым поведением.
| Этот раздел не завершён Причина: мини-пример |
Шаблоны функций и функции-элементы шаблонов
|
Разрешается добавлять специализации шаблона для любого стандартного библиотечного шаблона функции в пространство имён |
(до C++20) |
|
Объявление полной специализации любого стандартного библиотечного шаблона функции является неопределённым поведением. |
(начиная с C++20) |
| Этот раздел не завершён Причина: мини-пример |
Объявление полной специализации любой функции-элемента шаблонного класса стандартной библиотеки является неопределённым поведением:
| Этот раздел не завершён Причина: мини-пример |
Объявление полной специализации любого шаблона функции-элемента стандартного библиотечного класса или шаблона класса является неопределённым поведением:
| Этот раздел не завершён Причина: мини-пример |
Шаблоны переменных
|
Объявление полной или частичной специализации любого шаблона переменной из стандартной библиотеки является неопределённым поведением, за исключением случаев, когда это явно разрешено.
|
(начиная с C++14) |
|
(начиная с C++20) |
Явное создание шаблонов
Разрешается явно создавать экземпляр шаблона класса (начиная с C++20), определённого в стандартной библиотеке, только в том случае, если объявление зависит от имени по крайней мере одного определённого в программе типа и создание экземпляра соответствует требованиям стандартной библиотеки для исходного шаблона.
| Этот раздел не завершён Причина: мини-пример |
Программно-определяемые типы
Определяемые программой специализации это явные специализации или частичные специализации шаблонов, которые не являются частью стандартной библиотеки C++ и не определяются реализацией.
Программно-определяемые типы это незамкнутые классовые типы или типы перечислений, которые не являются частью стандартной библиотеки C++ и не определяются реализацией, или типом замыкания лямбда-выражений, не предоставляемых реализацией (начиная с C++11), или реализация определяемых программой специализаций.
Другие ограничения
Пространство имён std нельзя объявлять как встроенное пространство имён.
Ограничение адресации
Поведение программы на C++ не определено (возможно, некорректно), если она явно или неявно пытается сформировать указатель, ссылку (для свободных функций и статических функций-элементов) или указатель на элемент (для нестатических функций-элементов) для стандартной библиотечной функции или экземпляра шаблона стандартной библиотечной функции, если она не обозначена как адресуемая функция (смотрите ниже).
Следующий код приводит к неопределённому поведению и, возможно, не компилируется:
#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);
}
Назначенные адрессуемые функции
- Манипуляторы ввода/вывода:
- манипуляторы
fmtflags:- std::boolalpha
- std::boolalpha
- std::showbase
- std::showbase
- std::showpoint
- std::showpoint
- std::showpos
- std::showpos
- std::skipws
- std::skipws
- std::uppercase
- std::uppercase
- std::unitbuf
- std::unitbuf
- манипуляторы
adjustfield:- std::left
- std::left
- std::left
- манипуляторы
basefield:- std::hex
- std::hex
- std::hex
- манипуляторы
floatfield:- std::fixed
- std::fixed
- std::fixed
- std::fixed
- манипуляторы
basic_istream:- std::ws
- манипуляторы
basic_ostream:- std::endl
- std::ends
- std::flush
- std::emit_on_flush
- std::noemit_on_flush
- std::flush_emit
- манипуляторы
Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
| Номер | Применён | Поведение в стандарте | Корректное поведение |
|---|---|---|---|
| LWG 120 | C++98 | пользователи могли явно создавать экземпляры шаблонов стандартной библиотеки для типов, не определяемых пользователем |
запрещено |
| LWG 232 | C++98 | пользователи могут явно специализировать шаблоны стандартной библиотеки, если объявление зависит от определяемого пользователем имени с внешним связыванием (которое может ссылаться на неопределяемый пользователем тип) |
разрешено только для пользовательских типов |
| LWG 422 | C++98 | пользователи могли специализировать отдельные элементы или шаблоны чэлементов без специализации всего класса или шаблонного класса стандартной библиотеки |
поведение не определено |