Spec-Zone.ru › C++

Расширение пространства имён 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) в основном шаблоне, таким образом, чтобы их можно было использовать как целочисленные константные выражения.
  • Ни один из шаблонов, определённых в <type_traits>, не может быть специализирован для типа, определённого программой, за исключением std::common_type и std::basic_common_reference(начиная с C++20). Сюда входят характеристики типов и шаблон класса std::integral_constant.
  • Специализации std::hash для типов, определённых программой, должны удовлетворять требованиям Hash.
  • Специализации std::atomic должны иметь удалённый конструктор копирования, удалённый оператор присваивания копированием и constexpr-конструктор значения.
  • Специализации std::shared_ptr и std::weak_ptr должны удовлетворять требованиям CopyConstructible и CopyAssignable. Кроме того, специализации std::shared_ptr должны удовлетворять требованиям LessThanComparable и быть преобразуемыми в bool.
  • Специализации std::istreambuf_iterator должны иметь тривиальный конструктор копирования, constexpr-конструктор по умолчанию и тривиальный деструктор.
(начиная с C++11)
  • Специализировать std::unary_function и std::binary_function запрещено.
(до C++17)

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

Шаблоны функций и функции-члены шаблонов

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

(до C++20)

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

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

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

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

Шаблоны переменных

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

  • Специализации 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++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);
}

Функции, для которых разрешено получение адреса

  • Манипуляторы ввода-вывода:
    • Манипуляторы fmtflags:
      • std::boolalpha
      • std::noboolalpha
      • std::showbase
      • std::noshowbase
      • std::showpoint
      • std::noshowpoint
      • std::showpos
      • std::noshowpos
      • std::skipws
      • std::noskipws
      • std::uppercase
      • std::nouppercase
      • std::unitbuf
      • std::nounitbuf
    • Манипуляторы adjustfield:
      • std::internal
      • std::left
      • std::right
    • Манипуляторы basefield:
      • std::dec
      • std::hex
      • std::oct
    • Манипуляторы floatfield:
      • std::fixed
      • std::scientific
      • std::hexfloat
      • std::defaultfloat
    • Манипуляторы basic_istream:
      • std::ws
    • Манипуляторы basic_ostream:
      • std::endl
      • std::ends
      • std::flush
      • std::emit_on_flush
      • std::noemit_on_flush
      • std::flush_emit
(начиная с 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API