std::optional<T>::optional
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.
other содержит значение, инициализирует хранимое значение, как если бы прямая инициализация (но не прямая инициализация списком) объекта типа T выражением *other. Если other не содержит значения, конструирует объект, который не содержит значения.
- Этот конструктор определён как удалённый, если
std::is_copy_constructible_v<T>являетсяfalse. - Это тривиальный конструктор, если
std::is_trivially_copy_constructible_v<T>являетсяtrue.
other содержит значение, инициализирует хранимое значение, как если бы прямая инициализация (но не прямая инициализация списком) объекта типа T выражением std::move(*other) и не делает other пустым: перемещённый std::optional всё ещё содержит значение, но само значение перемещено. Если other не содержит значения, конструирует объект, который не содержит значения.
- Этот конструктор не участвует в разрешении перегрузки, если только
std::is_move_constructible_v<T>не являетсяtrue. - Это тривиальный конструктор, если
std::is_trivially_move_constructible_v<T>являетсяtrue.
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.
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.
T из аргументов std::forward<Args>(args)....
- Если выбранный конструктор
Tявляетсяconstexprконструктором, этот конструктор являетсяconstexprконструктором. - Функция не участвует в разрешении перегрузки, если только
std::is_constructible_v<T, Args...>не являетсяtrue.
T из аргументов ilist, std::forward<Args>(args)....
- Если выбранный конструктор
Tявляетсяconstexprконструктором, этот конструктор являетсяconstexprконструктором. - Функция не участвует в разрешении перегрузки, если только
std::is_constructible_v<T, std::initializer_list<U>&, Args...>не являетсяtrue.
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 | - | список инициализации, которым инициализируется содержащееся значение |
Исключения
T
.
T
. Имеет следующую
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 |
Смотрите также
|
(C++17)
|
создает объект
optional
(шаблон функции) |