Spec-Zone.ru › C++

Оборачивающий класс с присваиванием (C++20)

template<class T>
    requires std::copy_constructible<T> && std::is_object_v<T>
class /*copyable-box*/;
(с C++20)
(до C++23)
(только для примера*)
template<class T>
    requires std::move_constructible<T> && std::is_object_v<T>
class /*movable-box*/;
(с C++23)
(только для примера*)

ranges::single_view, ranges::repeat_view,(с C++23) и адаптеры диапазонов, которые хранят вызываемый объект, определяются с использованием шаблонного класса copyable-box(до C++23)movable-box(с C++23). Приведённое здесь имя используется только для примера.

Оборачивающий класс ведёт себя точно так же, как std::optional<T>, за исключением того, что конструктор по умолчанию, операторы копирующего присваивания и перемещающего присваивания (условно) отличаются от аналогичных операторов std::optional, что расширяет T до возможности присваивания при необходимости и гарантирует, что он всегда удовлетворяет copyable или movable(с C++23).

Если T уже copyable, или оба std::is_nothrow_move_constructible_v<T> и std::is_nothrow_copy_constructible_v<T> являются true, /*copyable-box*/<T> может хранить только объект T, так как он всегда содержит значение.

(до C++23)

Если T

  • уже copyable, или
  • является copy_constructible и оба std::is_nothrow_move_constructible_v<T> и std::is_nothrow_copy_constructible_v<T> являются true, или
  • не удовлетворяет copy_constructible, но удовлетворяет movable, или
  • не удовлетворяет copy_constructible, но std::is_nothrow_move_constructible_v<T> является true,

/*movable-box*/<T> может хранить только объект T, так как он всегда содержит значение.

(с C++23)

Параметры шаблона

T - тип хранимого значения, должен быть объектным типом, который моделирует copy_constructible(до C++23)move_constructible(с C++23)

Члены-функции

Конструктор по умолчанию

constexpr /*copyable-box*/() noexcept(std::is_nothrow_default_constructible_v<T>)
    requires std::default_initializable<T>
    : /*copyable-box*/(std::in_place) { }
(с C++20)
(до C++23)
constexpr /*movable-box*/() noexcept(std::is_nothrow_default_constructible_v<T>)
    requires std::default_initializable<T>
    : /*movable-box*/(std::in_place) { }
(с C++23)

Конструктор по умолчанию предоставляется тогда и только тогда, когда T моделирует default_initializable.

Оборачивающий класс, созданный с помощью конструктора по умолчанию, содержит объект T с инициализацией по умолчанию.

Операторы присваивания

(1)
constexpr /*copyable-box*/& operator=(const /*copyable-box*/& other);
    noexcept(/* see below */);
(с C++20)
(до C++23)
constexpr /*movable-box*/& operator=(const /*movable-box*/& other);
    noexcept(/* see below */) requires std::copy_constructible<T>;
(с C++23)
(2)
constexpr /*copyable-box*/& operator=(/*copyable-box*/&& other)
    noexcept(std::is_nothrow_move_constructible_v<T>);
(с C++20)
(до C++23)
constexpr /*movable-box*/& operator=(/*movable-box*/&& other)
    noexcept(std::is_nothrow_move_constructible_v<T>);
(с C++23)
1) Если std::copyable<T> не моделирует, оператор копирующего присваивания определяется следующим образом:

constexpr /*copyable-box*/& operator=(const /*copyable-box*/& other)
noexcept(std::is_nothrow_copy_constructible_v<T>)
{
if (this != std::addressof(other))
if (other)
emplace(*other);
else
reset();

return *this;
}

(до C++23)

constexpr /*movable-box*/& operator=(const /*movable-box*/& other)
noexcept(std::is_nothrow_copy_constructible_v<T>)
requires std::copy_constructible<T>
{
if (this != std::addressof(other))
if (other)
emplace(*other);
else
reset();

return *this;
}

(с C++23)
В противном случае он идентичен оператору копирующего присваивания std::optional.
2) Если std::movable<T> не моделирует, оператор перемещающего присваивания определяется следующим образом:

constexpr /*copyable-box*/& operator=(/*copyable-box*/&& other)
noexcept(std::is_nothrow_move_constructible_v<T>)
{
if (this != std::addressof(other))
if (other)
emplace(std::move(*other));
else
reset();

return *this;
}

(до C++23)

constexpr /*movable-box*/& operator=(/*movable-box*/&& other)
noexcept(std::is_nothrow_move_constructible_v<T>)
{
if (this != std::addressof(other))
if (other)
emplace(std::move(*other));
else
reset();

return *this;
}

(с C++23)
В противном случае он идентичен оператору перемещающего присваивания std::optional.

Члены, идентичные std::optional

Члены-функции

(конструктор)
создаёт объект optional
(публичный член-функции std::optional<T>)
(деструктор)
уничтожает содержимое, если оно есть
(публичный член-функции std::optional<T>)
operator=
присваивает содержимое
(публичный член-функции std::optional<T>)
Наблюдатели
operator->operator*
обращается к содержимому
(публичный член-функции std::optional<T>)
operator boolhas_value
проверяет, содержит ли объект значение
(публичный член-функции std::optional<T>)
Модификаторы
reset
уничтожает любое содержимое
(публичный член-функции std::optional<T>)
emplace
создаёт содержимое на месте
(публичный член-функции std::optional<T>)

Примечания

Оборачивающий класс copyable-box(до C++23)movable-box(с C++23) не содержит значения только в случае, если

  • T не моделирует movable или copyable, и соответственно при перемещении или копировании присваивания выбрасывается исключение, или
  • он инициализирован/присвоен из другого пустого оборачивающего класса.
END_OF_DOCUMENT_MARKER

До P2325R3 оборачивающий класс назывался semiregular-box в стандарте и всегда удовлетворял semiregular, так как конструктор по умолчанию всегда предоставлялся (что могло создать пустой оборачивающий класс).

END_OF_DOCUMENT_MARKER
Тест-функции макрос Значение Стандарт Функция
__cpp_lib_ranges 201911L (C++20) Библиотека диапазонов и ограниченные алгоритмы
202106L (C++20)
(DR)
Не-инициализируемые по умолчанию представления
202207L (C++23) Смягчение ограничений на адаптеры диапазонов, разрешающее использование типов, только перемещаемых

Отчёты о дефектах

Следующие отчёты о дефектах, меняющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применено к Поведение при публикации Правильное поведение
P2325R3 C++20 если T не default_initializable, конструктор по умолчанию
создаёт обёртку, которая не содержит значения
обёртка также
не default_initializable
LWG 3572 C++20 условные операторы присваивания не были constexpr сделаны constexpr

См. также

ranges::single_viewviews::single
(C++20)
представление, содержащее единственный элемент заданного значения
(шаблон класса) (объект точек кастомизации)
ranges::repeat_viewviews::repeat
(C++23)
представление, состоящее из генерируемой последовательности, повторяющей одно и то же значение
(шаблон класса) (объект точек кастомизации)
ranges::filter_viewviews::filter
(C++20)
представление, состоящее из элементов диапазона, удовлетворяющих предикату
(шаблон класса) (объект адаптера диапазонов)
ranges::transform_viewviews::transform
(C++20)
представление последовательности, применяющей функцию преобразования к каждому элементу
(шаблон класса) (объект адаптера диапазонов)
ranges::take_while_viewviews::take_while
(C++20)
представление, состоящее из начальных элементов другого представления, до тех пор, пока предикат не вернёт true
(шаблон класса) (объект адаптера диапазонов)
ranges::drop_while_viewviews::drop_while
(C++20)
представление, состоящее из элементов другого представления, пропускающее начальную подпоследовательность элементов, пока предикат не вернёт false
(шаблон класса) (объект адаптера диапазонов)
ranges::zip_transform_viewviews::zip_transform
(C++23)
представление, состоящее из кортежей результатов применения функции преобразования к соответствующим элементам адаптированных представлений
(шаблон класса) (объект точек кастомизации)
ranges::adjacent_transform_viewviews::adjacent_transform
(C++23)
представление, состоящее из кортежей результатов применения функции преобразования к смежным элементам адаптированного представления
(шаблон класса) (объект адаптера диапазонов)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/w/cpp/ranges/copyable_wrapper

Spec-Zone.ru

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