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 и long double, не определена.
  • Специализации std::numeric_limits должны определять все члены, объявленные static const(до C++11)static constexpr(с 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)

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

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

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

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

(с 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++ не определено (возможно, некорректно), если она явно или неявно пытается сформировать указатель, ссылку (для свободных функций и статических функций-членов) или указатель-на-член (для нестатических функций-членов) на функцию стандартной библиотеки или экземпляр шаблона функции стандартной библиотеки, если функция не обозначена как адресуемая функция (см. ниже).

Следующий код был корректно определён в 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
}

Определённые адресуемые функции

  • манипуляторы ввода-вывода:
    • манипуляторы 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/w/cpp/language/extending_std

Spec-Zone.ru

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