Assignable wrapper (C++20)

From cppreference.com
< cpp‎ | ranges
 
 
Ranges library
Range access
Range conversions
(C++23)
Range primitives



Dangling iterator handling
Range concepts
Views

Range factories
Range adaptors
Range generators
Range adaptor objects
Range adaptor closure objects
Helper items
copyable-box
movable-box
(until C++23)(C++23)


 
template<class T>

    requires std::copy_constructible<T> && std::is_object_v<T>

class /*copyable-box*/;
(since C++20)
(until C++23)
(exposition only*)
template<class T>

    requires std::move_constructible<T> && std::is_object_v<T>

class /*movable-box*/;
(since C++23)
(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 copyableor 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.

(until C++23)

If T

/*movable-box*/<T> may store only a T object, because it always contains a value.

(since C++23)

Template parameters

T - the type of the contained value, must be an object type that models copy_constructible (until C++23)move_constructible (since C++23)

Member functions

Default constructor

constexpr /*copyable-box*/() noexcept(std::is_nothrow_default_constructible_v<T>)

    requires std::default_initializable<T>

    : /*copyable-box*/(std::in_place) { }
(since C++20)
(until C++23)
constexpr /*movable-box*/() noexcept(std::is_nothrow_default_constructible_v<T>)

    requires std::default_initializable<T>

    : /*movable-box*/(std::in_place) { }
(since C++23)

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

(1)
constexpr /*copyable-box*/& operator=(const /*copyable-box*/& other);
    noexcept(/* see below */);
(since C++20)
(until C++23)
constexpr /*movable-box*/& operator=(const /*movable-box*/& other);
    noexcept(/* see below */) requires std::copy_constructible<T>;
(since C++23)
(2)
constexpr /*copyable-box*/& operator=(/*copyable-box*/&& other)
    noexcept(std::is_nothrow_move_constructible_v<T>);
(since C++20)
(until C++23)
constexpr /*movable-box*/& operator=(/*movable-box*/&& other)
    noexcept(std::is_nothrow_move_constructible_v<T>);
(since C++23)
1) If std::copyable<T> is not modeled, the copy assignment operator is equivalently defined as:

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;
}

(until 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;
}

(since C++23)
Otherwise, it is identical to the copy assignment operator of std::optional.
2) If std::movable<T> is not modeled, the move assignment operator is equivalently defined as:

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;
}

(until 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;
}

(since C++23)
Otherwise, it is identical to the move assignment operator of std::optional.

Members identical to std::optional

Member functions

constructs the optional object
(public member function of std::optional<T>)
destroys the contained value, if there is one
(public member function of std::optional<T>)
assigns contents
(public member function of std::optional<T>)
Observers
accesses the contained value
(public member function of std::optional<T>)
checks whether the object contains a value
(public member function of std::optional<T>)
Modifiers
destroys any contained value
(public member function of std::optional<T>)
constructs the contained value in-place
(public member function of std::optional<T>)

Notes

A copyable-box (until C++23)movable-box (since C++23) does not contain a value only if

  • T does not model movable or copyable, 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 Comment
__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

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 T is not default_initializable, the default constructor
constructs 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

See also

a view that contains a single element of a specified value
(class template) (customization point object)
a view consisting of a generated sequence by repeatedly producing the same value
(class template) (customization point object)
a view that consists of the elements of a range that satisfies a predicate
(class template) (range adaptor object)
a view of a sequence that applies a transformation function to each element
(class template) (range adaptor object)
a view consisting of the initial elements of another view, until the first element on which a predicate returns false
(class template) (range adaptor object)
a 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)
a view consisting of tuples of results of application of a transformation function to corresponding elements of the adapted views
(class template) (customization point object)
a view consisting of tuples of results of application of a transformation function to adjacent elements of the adapted view
(class template) (range adaptor object)