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(/* смотрите ниже */); |
(3) | (начиная с C++17) |
| (4) | ||
template < class U > optional( const optional<U>& other ); |
(начиная с C++17) (до C++20) (conditionally explicit) |
|
template < class U > constexpr optional( const optional<U>& other ); |
(начиная с C++20) (conditionally explicit) |
|
| (5) | ||
template < class U > optional( optional<U>&& other ); |
(начиная с C++17) (до C++20) (conditionally explicit) |
|
template < class U > constexpr optional( optional<U>&& other ); |
(начиная с C++20) (conditionally explicit) |
|
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 = T > constexpr optional( U&& value ); |
(8) | (начиная с C++17) (conditionally explicit) |
Создаёт новый объект 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>, т.е. все следующие 8 значений являютсяfalse:std::is_constructible_v<T, std::optional<U>&>std::is_constructible_v<T, const std::optional<U>&>std::is_constructible_v<T, std::optional<U>&&>std::is_constructible_v<T, const std::optional<U>&&>std::is_convertible_v<std::optional<U>&, T>std::is_convertible_v<const std::optional<U>&, T>std::is_convertible_v<std::optional<U>&&, T>std::is_convertible_v<const std::optional<U>&&, T>
- Этот конструктор является
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>, т.е. все следующие 8 значений являютсяfalse:std::is_constructible_v<T, std::optional<U>&>std::is_constructible_v<T, const std::optional<U>&>std::is_constructible_v<T, std::optional<U>&&>std::is_constructible_v<T, const std::optional<U>&&>std::is_convertible_v<std::optional<U>&, T>std::is_convertible_v<const std::optional<U>&, T>std::is_convertible_v<std::optional<U>&&, T>std::is_convertible_v<const std::optional<U>&&, T>
- Этот конструктор является
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.
Параметры
| other | — | другой объект optional, содержащееся в котором значение копируется
|
| value | — | значение, которым инициализировать содержащееся значение |
| args... | — | аргументы для инициализации содержащегося значения |
| ilist | — | список инициализаторов, с помощью которых инициализировать содержащееся значение |
Исключения
T.T. Имеет следующую noexcept(std::is_nothrow_move_constructible<T>::value)T.Правила вывода
Примечания
До разрешения LWG проблема 3836 создание std::optional<bool> из std::optional<U> выбирало бы перегрузку (8) вместо перегрузок (4,5), если U не равно bool. Это связано с тем, что перегрузки (4,5) не участвовали в разрешении перегрузки, если 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_0); // ДЕФЕКТ (LWG 3836): содержит true,
// поскольку op_0 содержит значение, даже если
// инициализация bool из этого значения даёт false
Пример
#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 с использованием принципов вывода
// для выбора типа
std::optional o6(std::string{"вывод"});
std::cout << *o2 << ' ' << *o3 << ' ' << *o4 << ' ' << *o5 << ' ' << *o6 << '\n';
}
Вывод:
1 1 abc AAA вывод
Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
| Номер | Применён | Поведение в стандарте | Корректное поведение |
|---|---|---|---|
| LWG 3836 | C++17 | при создании std::optional<bool> из std::optional<U> разрешениеперегрузки выберет перегрузку (8), если U не bool
|
в этом случае всегда выбирает конвертирующий конструктор копирования/перемещения |
| WG не указан | C++17 | конструкторы копирования/перемещения могут быть нетривиальными, даже если базовый конструктор тривиален |
требуется для распространения тривиальности |
| WG не указан | C++20 | конструкторы преобразования из другого std::optional не были constexpr,в то время как необходимые операции могут быть в C++20 |
сделаны constexpr |
Смотрите также
(C++17) |
создаёт объект optional (шаблон функции) |