Namespaces
Variants

std::optional<T>::optional

From ru.cppreference.net
 
 
Библиотека утилит
Поддержка языка
Поддержка типов (базовые типы, RTTI)
Макросы проверки возможностей библиотеки (C++20)
Программные утилиты
Функции с переменным числом аргументов
Поддержка корутин (C++20)
Поддержка контрактов (C++26)
Трёхстороннее сравнение
(C++20)
(C++20)(C++20)(C++20)    
(C++20)(C++20)(C++20)

Общие утилиты
Операторы отношений (устарело в C++20)
 
 
constexpr optional() noexcept;
constexpr optional( std::nullopt_t ) noexcept;
(1) (начиная с C++17)
constexpr optional( const optional& other );
(2) (начиная с C++17)
constexpr optional( optional&& other ) noexcept(/* see below */);
(3) (начиная с C++17)
template < class U >
optional( const optional<U>& other );
(4) (начиная с C++17)
(constexpr начиная с C++20)
(условно явный)
template < class U >
optional( optional<U>&& other );
(5) (начиная с C++17)
(constexpr начиная с C++20)
(условно явный)
template< class... Args >
constexpr explicit optional( std::in_place_t, Args&&... args );
(6) (начиная с C++17)
template< class U, class... Args >
constexpr explicit optional( std::in_place_t,
                             std::initializer_list<U> ilist,
                             Args&&... args );
(7) (начиная с C++17)
template < class U = std::remove_cv_t<T> >
constexpr optional( U&& value );
(8) (начиная с C++17)
(условно явный)

Конструирует новый объект optional.

1) Конструирует объект, который не содержит значения.
2) Конструктор копирования: Если other содержит значение, инициализирует хранимое значение, как если бы прямая инициализация (но не прямая инициализация списком) объекта типа T выражением *other. Если other не содержит значения, конструирует объект, который не содержит значения.
  • Этот конструктор определён как удалённый, если std::is_copy_constructible_v<T> является false.
  • Это тривиальный конструктор, если std::is_trivially_copy_constructible_v<T> является true.
3) Конструктор перемещения: Если other содержит значение, инициализирует хранимое значение, как если бы прямая инициализация (но не прямая инициализация списком) объекта типа T выражением std::move(*other) и не делает other пустым: перемещённый std::optional всё ещё содержит значение, но само значение перемещено. Если other не содержит значения, конструирует объект, который не содержит значения.
  • Этот конструктор не участвует в разрешении перегрузки, если только std::is_move_constructible_v<T> не является true.
  • Это тривиальный конструктор, если std::is_trivially_move_constructible_v<T> является true.
4) Преобразующий конструктор копирования: Если other не содержит значения, конструирует объект optional, который не содержит значения. В противном случае конструирует объект optional, который содержит значение, инициализированное, как если бы прямая инициализация (но не прямая инициализация списком) объекта типа T выражением *other.
  • Этот конструктор не участвует в разрешении перегрузки, если только не выполнены следующие условия:
    • std::is_constructible_v<T, const U&> является true.
    • Если T не является (возможно cv-квалифицированным) bool, T не является конструируемым или преобразуемым из любого выражения типа (возможно const) std::optional<U>, т.е. converts_from_any_cvref<T, std::optional<U>> является false, где converts_from_any_cvref описано ниже.
  • Этот конструктор является explicit тогда и только тогда, когда std::is_convertible_v<const U&, T> является false.
5) Преобразующий конструктор перемещения: Если other не содержит значения, конструирует объект optional, который не содержит значения. В противном случае конструирует объект optional, который содержит значение, инициализированное, как если бы прямая инициализация (но не прямая инициализация списком) объекта типа T выражением std::move(*other).
  • Этот конструктор не участвует в разрешении перегрузки, если только не выполнены следующие условия:
    • std::is_constructible_v<T, U&&> является true.
    • Если T не является (возможно cv-квалифицированным) bool, T не является конструируемым или преобразуемым из любого выражения типа (возможно const) std::optional<U>, т.е. converts_from_any_cvref<T, std::optional<U>> является false, где converts_from_any_cvref описано ниже.
  • Этот конструктор является explicit тогда и только тогда, когда std::is_convertible_v<U&&, T> является false.
6) Конструирует объект optional, который содержит значение, инициализированное, как если бы прямая инициализация (но не прямая инициализация списком) объекта типа T из аргументов std::forward<Args>(args)....
  • Если выбранный конструктор T является constexpr конструктором, этот конструктор является constexpr конструктором.
  • Функция не участвует в разрешении перегрузки, если только std::is_constructible_v<T, Args...> не является true.
7) Конструирует объект optional, который содержит значение, инициализированное, как если бы прямая инициализация (но не прямая инициализация списком) объекта типа T из аргументов ilist, std::forward<Args>(args)....
  • Если выбранный конструктор T является constexpr конструктором, этот конструктор является constexpr конструктором.
  • Функция не участвует в разрешении перегрузки, если только std::is_constructible_v<T, std::initializer_list<U>&, Args...> не является true.
8) Конструирует объект optional, который содержит значение, инициализированное, как если бы прямая инициализация (но не прямая инициализация списком) объекта типа T выражением std::forward<U>(value).
  • Если выбранный конструктор T является constexpr конструктором, этот конструктор является constexpr конструктором.
  • Этот конструктор не участвует в разрешении перегрузки, если только не выполнены следующие условия:
    • std::is_constructible_v<T, U&&> является true.
    • std::decay_t<U>(до C++20)std::remove_cvref_t<U>(начиная с C++20) не является ни std::in_place_t, ни std::optional<T>.
    • Если T является (возможно cv-квалифицированным) bool, std::decay_t<U>(до C++20)std::remove_cvref_t<U>(начиная с C++20) не является специализацией std::optional.
  • Этот конструктор является explicit тогда и только тогда, когда std::is_convertible_v<U&&, T> является false.

Вспомогательный шаблон переменной converts_from_any_cvref эквивалентен:

template< class T, class W >
constexpr bool converts_from_any_cvref =
    std::disjunction_v<std::is_constructible<T, W&>, std::is_convertible<W&, T>,
                       std::is_constructible<T, W>, std::is_convertible<W, T>,
                       std::is_constructible<T, const W&>, std::is_convertible<const W&, T>,
                       std::is_constructible<T, const W>, std::is_convertible<const W, T>>;

Параметры

other - другой optional объект, чьё содержащееся значение копируется
value - значение, которым инициализируется содержащееся значение
args... - аргументы, которыми инициализируется содержащееся значение
ilist - список инициализации, которым инициализируется содержащееся значение

Исключения

3) Выбрасывает любое исключение, выброшенное конструктором T .
4) Выбрасывает любое исключение, выброшенное конструктором T . Имеет следующую
noexcept спецификацию:
noexcept ( std:: is_nothrow_move_constructible < T > :: value )
5-9) Выбрасывает любое исключение, выброшенное конструктором T .

Примечания

До разрешения LWG issue 3836 , конструирование std:: optional < bool > из std:: optional < U > выбирало перегрузку ( 9 ) вместо перегрузок ( 5,6 ) , если U не является bool . Это происходило потому, что перегрузки ( 5,6 ) не участвовали в разрешении перегрузки, если T ( bool в данном случае) может быть сконструирован или преобразован из std:: optional < U > , но std::optional::operator bool делает такое преобразование возможным для любого U .

В результате, созданный std:: optional < bool > всегда содержит значение. Это значение определяется тем, содержит ли предоставленный std:: optional < U > объект значение, а не bool значением, прямым образом инициализированным из содержащегося значения:

std::optional<bool> op_false(false);
std::optional<int> op_zero(0);
std::optional<int> from_bool(op_false); // OK: содержит 0 (инициализировано из false)
std::optional<bool> from_int(op_zero);  // ДЕФЕКТ (LWG 3836): содержит true, потому что
                                        // op_zero содержит значение, даже если инициализация
                                        // bool из этого значения дает false
Макрос тестирования возможностей Значение Стандарт Функция
__cpp_lib_optional 202106L (C++20)
(DR20)
Полностью constexpr ( 5,6 )

Пример

#include <iostream>
#include <optional>
#include <string>
int main()
{
    std::optional<int> o1, // пустой
                       o2 = 1, // инициализация из rvalue
                       o3 = o2; // копирующий конструктор
    // вызов конструктора std::string( initializer_list<CharT> )
    std::optional<std::string> o4(std::in_place, {'a', 'b', 'c'});
    // вызов конструктора std::string( size_type count, CharT ch )
    std::optional<std::string> o5(std::in_place, 3, 'A');
    // Перемещающий конструктор из std::string с использованием deduction guide для выбора типа
    std::optional o6(std::string{"deduction"});
    std::cout << *o2 << ' ' << *o3 << ' ' << *o4 << ' ' << *o5  << ' ' << *o6 << '\n';
}

Вывод:

1 1 abc AAA deduction

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

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

DR Applied to Behavior as published Correct behavior
LWG 3836 C++17 при конструировании std:: optional < bool >
из std:: optional < U > разрешение перегрузки
выбирало перегрузку ( 9 ) если U не является bool
всегда выбирает
преобразующий конструктор копирования/перемещения
в этом случае
LWG 3886 C++17 аргумент шаблона по умолчанию для перегрузки ( 9 ) был T изменён на std:: remove_cv_t < T >
P0602R4 C++17 конструкторы копирования/перемещения могли быть нетривиальными
даже если базовый конструктор тривиален
требуется
сохранять тривиальность
P2231R1 C++20 перегрузки ( 5,6 ) из другого std::optional не были constexpr сделаны constexpr

Смотрите также

создает объект optional
(шаблон функции)