Расширение пространства имён std
Добавление объявлений в std
Добавление объявлений или определений в пространство имён std или в любое пространство имён, вложенное в std, является неопределённым поведением, за исключением нескольких случаев, перечисленных ниже.
#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};
}
}
Добавление специализаций шаблонов
Шаблоны классов
Разрешается добавлять специализации шаблонов для любых шаблонов классов стандартной библиотеки в пространство имён std только в том случае, если объявление зависит как минимум от одного типа, определённого программой, а специализация удовлетворяет всем требованиям исходного шаблона, кроме случаев, когда такие специализации запрещены.
// 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(); }
};
- Специализация шаблона
std::complexдля любого типа, кроме float, double и longdouble, не специфицирована. - Специализации
std::numeric_limitsдолжны определять все члены, объявленные как staticconst(до C++11)staticconstexpr(начиная с C++11) в основном шаблоне, таким образом, чтобы их можно было использовать как целочисленные константные выражения.
| (начиная с C++11) |
| (до C++17) |
Объявление полной или частичной специализации любого вложенного шаблона класса класса или шаблона класса стандартной библиотеки является неопределённым поведением.
Шаблоны функций и функции-члены шаблонов
| Разрешается добавлять специализации шаблонов для любых шаблонов функций стандартной библиотеки в пространство имён | (до C++20) |
| Объявление полной специализации любого шаблона функции стандартной библиотеки является неопределённым поведением. | (начиная с C++20) |
Объявление полной специализации любой функции-члена шаблона класса стандартной библиотеки является неопределённым поведением:
Объявление полной специализации любого шаблона функции-члена класса или шаблона класса стандартной библиотеки является неопределённым поведением:
Шаблоны переменных
| Объявление полной или частичной специализации любого шаблона переменной стандартной библиотеки является неопределённым поведением, кроме случаев, когда это явно разрешено.
| (начиная с C++14) |
Явная инстанциация шаблонов
Разрешается явно инстанцировать шаблон класса (начиная с C++20), определённый в стандартной библиотеке, только в том случае, если объявление зависит от имени как минимум одного типа, определённого программой, а инстанциация удовлетворяет требованиям стандартной библиотеки к исходному шаблону.
Другие ограничения
Пространство имён std нельзя объявлять как встроенное пространство имён.
Ограничение на получение адресаПоведение программы на C++ не специфицировано (возможна некорректность программы), если она явно или неявно пытается получить указатель или ссылку (для свободных функций и статических функций-членов) либо указатель на член (для нестатических функций-членов) стандартной библиотечной функции или инстанциации шаблона функции стандартной библиотеки, если только эта функция не обозначена как функция, адрес которой можно получить (см. ниже). Следующий код корректно работал в C++17, но начиная с C++20 приводит к неспецифицированному поведению и может не компилироваться: #include <cmath>
#include <memory>
int main()
{
// by unary operator&
auto fptr0 = &static_cast<float(&)(float, float)>(std::betaf);
// by std::addressof
auto fptr1 = std::addressof(static_cast<float(&)(float, float)>(std::betaf));
// by function-to-pointer implicit conversion
auto fptr2 = static_cast<float(&)(float)>(std::riemann_zetaf);
// forming a reference
auto& fref = static_cast<float(&)(float)>(std::riemann_zetaf);
}
Функции, для которых разрешено получение адреса
| (начиная с C++20) |
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были применены задним числом к ранее опубликованным стандартам C++.
| DR | Применяется к | Поведение согласно опубликованной версии | Корректное поведение |
|---|---|---|---|
| LWG 120 | C++98 | пользователи могли явно инстанцировать шаблоны стандартной библиотеки для типов, не определённых пользователем | запрещено |
| LWG 232 | C++98 | пользователи могли явно специализировать шаблоны стандартной библиотеки, если объявление зависело от определённого пользователем имени с внешним связыванием (которое может ссылаться на тип, не определённый пользователем) | разрешено только для типов, определённых пользователем |
| LWG 422 | C++98 | пользователи могли специализировать отдельные члены или шаблоны-члены, не специализируя весь класс или шаблон класса стандартной библиотеки | в этом случае поведение не определено |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/extending_std