Пространства имён
Варианты
Действия

Расширение пространства имён std

Материал из cppreference.com
< cpp‎ | language
 
 
Язык С++
Общие темы
Управление потоком
Операторы условного выполнения
if
Операторы итерации (циклы)
Операторы перехода
Функции
Объявление функции
Выражение лямбда-функции
Спецификатор inline
Спецификации динамических исключений (до C++17*)
Спецификатор noexcept (C++11)
Исключения
Пространства имён
Типы
Спецификаторы
decltype (C++11)
auto (C++11)
alignas (C++11)
Спецификаторы длительности хранения
Инициализация
Выражения
Альтернативные представления
Литералы
Логические - Целочисленные - С плавающей запятой
Символьные - Строковые - nullptr (C++11)
Определяемые пользователем (C++11)
Утилиты
Атрибуты (C++11)
Types
Объявление typedef
Объявление псевдонима типа (C++11)
Casts
Неявные преобразования - Явные преобразования
static_cast - dynamic_cast
const_cast - reinterpret_cast
Выделение памяти
Классы
Свойства функции класса
explicit (C++11)
static
Специальные функции-элементы
Шаблоны
Разное
 

Содержание

[править] Добавление объявлений в 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::hash для определяемых программой типов должны соответствовать требованиям Hash.
  • Специализации std::atomic должны иметь удалённый конструктор копирования, удалённый оператор присваивания копированием и constexpr конструктор значения.
  • Специализации std::istreambuf_iterator должны иметь тривиальный конструктор копирования, constexpr конструктор по умолчанию и тривиальный деструктор.
(начиная с C++11)
(до C++17)

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

[править] Шаблоны функций и функции-элементы шаблонов

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

(до C++20)

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

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

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

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

[править] Шаблоны переменных

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

(начиная с C++14)
  • Специализации std::disable_sized_sentinel_for, std::ranges::disable_sized_range, std::ranges::enable_view и std::ranges::enable_borrowed_range должны использоваться в константных выражениях и иметь тип const bool. А также
    • std::disable_sized_sentinel_for может быть специализирована для cv-неквалифицированных типов объектов, не массивов, S и I, по крайней мере, один из которых является программно-определяемым типом.
    • std::ranges::disable_sized_range, std::ranges::enable_view и std::ranges::enable_borrowed_range могут быть специализированы для cv-неквалифицированных программно определяемых типов.
  • Каждый шаблон математической константной переменной может быть частично или явно специализированным, при условии, что специализация зависит от определённого в программе типа.
(начиная с 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);
}

[править] Назначенные адрессуемые функции

[править] Отчёты о дефектах

Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:

Номер Применён Поведение в стандарте Корректное поведение
LWG 120 C++98 пользователи могли явно создавать экземпляры шаблонов стандартной
библиотеки для типов, не определяемых пользователем
запрещено
LWG 232 C++98 пользователи могут явно специализировать шаблоны стандартной
библиотеки, если объявление зависит от определяемого пользователем
имени с внешним связыванием (которое может ссылаться на
неопределяемый пользователем тип)
разрешено только для
пользовательских типов
LWG 422 C++98 пользователи могли специализировать отдельные элементы или
шаблоны чэлементов без специализации всего класса или шаблонного
класса стандартной библиотеки
поведение не определено