Copyable wrapper (C++20)

< cpp‎ | ranges
template<class T>

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

class /*copyable-box*/;
(since C++20)

ranges::single_view and range adaptors that store an invocable object are specified in terms of an exposition-only class template copyable-box. The name copyable-box is for exposition purposes only.

/*copyable-box*/<T> 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 makes it always satisfy copyable.

If T is already copyable, or both std::is_nothrow_move_constructible_v<T> and std::is_nothrow_move_constructible_v<T> are true, /*copyable-box*/<T> may only stores a T object, because it always contains a value.


[edit] Template parameters

T - the type of the contained value, must be a object type that models copy_constructible

[edit] Member functions


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

    requires std::default_initializable<T>

    : /*copyable-box*/(std::in_place) { }
(since C++20)

The default constructor is provided if and only if T models default_initializable.

A default-constructed /*copyable-box*/<T> contains a value-initialized T object.


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

/*copyable-box*/& operator=(const /*copyable-box*/& other)
    if (this != std::addressof(other)) {
        if (other) emplace(*other);
        else reset();
    return *this;

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:

/*copyable-box*/& operator=(/*copyable-box*/&& other)
    if (this != std::addressof(other)) {
        if (other) emplace(std::move(*other));
        else reset();
    return *this;

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>) [edit]
destroys the contained value, if there is one
(public member function of std::optional<T>) [edit]
assigns contents
(public member function of std::optional<T>) [edit]
accesses the contained value
(public member function of std::optional<T>) [edit]
checks whether the object contains a value
(public member function of std::optional<T>) [edit]
destroys any contained value
(public member function of std::optional<T>) [edit]
constructs the contained value in-place
(public member function of std::optional<T>) [edit]

[edit] Notes

A copyable-box does not contains 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).

[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 T is not default_initializable, the default constructor
constructs a wrapper which does not contain a value
the wrapper is also
not default_initializable

[edit] See also

a view that contains a single element of a specified value
(class template) (customization point object) [edit]
a view that consists of the elements of a range that satisfies a predicate
(class template) (range adaptor object) [edit]
a view of a sequence that applies a transformation function to each element
(class template) (range adaptor object) [edit]
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) [edit]
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) [edit]