Расширение пространства имен 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 и 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++ не определено (возможно, некорректно), если она явно или неявно пытается сформировать указатель, ссылку (для свободных функций и статических функций-членов) или указатель-на-член (для нестатических функций-членов) на функцию стандартной библиотеки или экземпляр шаблона функции стандартной библиотеки, если функция не обозначена как адресуемая функция (см. ниже). Следующий код был корректно определён в C++17, но приводит к неопределённому поведению и, возможно, не скомпилируется с C++20: #include <cmath>
#include <memory>
int main()
{
auto fptr0 = &static_cast<float(&)(float, float)>(std::betaf); // by unary operator&
auto fptr1 = std::addressof(static_cast<float(&)(float, float)>(std::betaf)); // by std::addressof
auto fptr2 = static_cast<float(&)(float)>(std::riemann_zetaf); // by function-to-pointer implicit conversion
auto& fref = static_cast<float(&)(float)>(std::riemann_zetaf); // forming a reference
}Определённые адресуемые функции
|
(с 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/w/cpp/language/extending_std