Assignable wrapper (C++20)
              requires std::copy_constructible <T> && std::is_object_v <T>
(until C++23)
(exposition only*)
    requires std::move_constructible <T> && std::is_object_v <T>
(exposition only*)
ranges::single_view , ranges::repeat_view,(since C++23) and range adaptors that store an invocable object are specified in terms of an exposition-only class template copyable-box(until C++23)movable-box(since C++23). The name shown here is for exposition purposes only.
The wrapper behaves exactly like std::optional <T>, except that the default constructor, copy assignment operator, and move assignment operator are (conditionally) different from those of std::optional , which augments T with assignability when needed and makes it always satisfy copyable or movable (since C++23).
If T is already copyable, or both std::is_nothrow_move_constructible_v <T> and std::is_nothrow_copy_constructible_v <T> are true, /*copyable-box*/<T> may store only a T object, because it always contains a value.
If T
-  is already copyable, or
-  is copy_constructibleand both std::is_nothrow_move_constructible_v <T> and std::is_nothrow_copy_constructible_v <T> are true, or
-  does not satisfy copy_constructiblebut satisfiesmovable, or
-  does not satisfy copy_constructiblebut std::is_nothrow_move_constructible_v <T> is true,
/*movable-box*/<T> may store only a T object, because it always contains a value.
Contents
[edit] Template parameters
copy_constructible (until C++23)move_constructible (since C++23)
[edit] Member functions
Default constructor
    requires std::default_initializable <T>
(until C++23)
    requires std::default_initializable <T>
The default constructor is provided if and only if T models default_initializable.
A default-constructed wrapper contains a value-initialized T object.
Assignment operators
noexcept(/* see below */);
(until C++23)
noexcept(/* see below */) requires std::copy_constructible <T>;
noexcept(std::is_nothrow_move_constructible_v <T>);
(until C++23)
noexcept(std::is_nothrow_move_constructible_v <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;
}
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;
}
std::optional.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;
}
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;
}
std::optional.Members identical to std::optional
Member functions
Observers
Modifiers
[edit] Notes
A copyable-box(until C++23)movable-box(since C++23) does not contain a value only if
-  Tdoes not modelmovableorcopyable, and an exception is thrown on move assignment or copy assignment respectively, or
- it is initialized/assigned from another valueless wrapper.
Before P2325R3, the wrapper was called semiregular-box in the standard and always satisfied semiregular, as the default constructor was always provided (which might construct a valueless wrapper).
| Feature-test macro | Value | Std | Feature | 
|---|---|---|---|
| __cpp_lib_ranges | 201911L | (C++20) | Ranges library and constrained algorithms | 
| 202106L | (C++20) (DR) | Non-default-initializable views | |
| 202207L | (C++23) | Relaxing range adaptors to allow for move-only types | 
[edit] Defect reports
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
| DR | Applied to | Behavior as published | Correct behavior | 
|---|---|---|---|
| P2325R3 | C++20 | if Tis notdefault_initializable, the default constructorconstructs a wrapper which does not contain a value | the wrapper is also not default_initializable | 
| LWG 3572 | C++20 | conditionally different assignment operators were not constexpr | made constexpr | 
[edit] See also
view that contains a single element of a specified value(class template) (customization point object)[edit]
view consisting of a generated sequence by repeatedly producing the same value(class template) (customization point object)[edit]
view that consists of the elements of a range that satisfies a predicate(class template) (range adaptor object)[edit]
view of a sequence that applies a transformation function to each element(class template) (range adaptor object)[edit]
view consisting of the initial elements of another view, until the first element on which a predicate returns false(class template) (range adaptor object)[edit]
view consisting of the elements of another view, skipping the initial subsequence of elements until the first element where the predicate returns false(class template) (range adaptor object)[edit]
view consisting of results of application of a transformation function to corresponding elements of the adapted views(class template) (customization point object)[edit]