Skip to content

Latest commit

 

History

History
133 lines (94 loc) · 4.28 KB

P2483R0.md

File metadata and controls

133 lines (94 loc) · 4.28 KB
title document date audience author toc
Support Non-copyable Types for `single_view`
P2483R0
2021-09-30
LEWG
name email
Hui Xie
false

Introduction

This paper proposes allowing single_view to hold non-copyable types.

Motivation and Scope

Currently, single_view requires the object that it holds to satisfy std::copy_constructible concept. This makes the single_view not usable with move only types. For example, the following code is invalid

// foo is move only type
foo make_foo();

std::views::single(make_foo()) // | more_pipe_lines

In the original c++ 20 ranges proposal, the view concept requires semiregular, thus all view implementations have to be copyable. However, after [@P1456R1], view no long requires implementations to be copyable but only movable, so technically the std::copy_constructible constraint can be relaxed to std::move_constructible for the types that single_view holds.

::: cmptable

Before

// foo is move only type
foo make_foo();

std::views::single(std::make_shared<foo>(make_foo()))
  | std::views::transform([](const auto& f) -> decltype(auto) {
      return (*f);
    })
  | // more_pipe_lines

After

// foo is move only type
foo make_foo();

std::views::single(make_foo()) // | more_pipe_lines

:::

Impact on the Standard

This proposal is a pure library extension.

Proposed Wording

Modify [ranges.syn]{.sref}

// [range.single], single view
template<@[`copy_­constructible`]{.rm}[`move_­constructible`]{.add}@ T>
    requires is_object_v<T>
  class single_view;

Modify [range.single.view]{.sref}

namespace std::ranges {
  template<@[`copy_­constructible`]{.rm}[`move_­constructible`]{.add}@ T>
    requires is_object_v<T>
  class single_view : public view_interface<single_view<T>> {
  private:
    @[_copyable-box_]{.rm}[_movable-box_]{.add}@<T> value_;             // exposition only (see [range.@[copy]{.rm}[move]{.add}@.wrap])

public:
  single_view() requires default_initializable<T> = default;
  constexpr explicit single_view(const T& t) @[`requires copy_constructible<T>`]{.add}@;
  constexpr explicit single_view(T&& t);
constexpr explicit single_view(const T& t) @[`requires copy_constructible<T>`]{.add}@;

[1]{.pnum} Effects: Initializes value_­ with t.

Add a new section [range.move.wrap] under [range.adaptors]{.sref}

::: add Movable wrapper

[1]{.pnum} @_movable-box<T>_@ behaves exactly like optional<T> with the following differences:

  • [1.1]{.pnum} @_movable-box<T>_@ constrains its type parameter T with move_constructible<T> && is_object_v<T>

  • [1.2]{.pnum} The default constructor of @_movable-box<T>_@ is equivalent to:

constexpr @_movable-box_@() noexcept(is_nothrow_default_constructible_v<T>)
    requires default_initializable<T>
  : @_movable-box_@(){in_place}
{}
  • [1.3]{.pnum} If movable<T> is not modelled, the move assignment operator is equivalent to:
@_movable-box_@& operator=(@_movable-box_@&& that)
  noexcept(is_nothrow_move_constructible_v<T>)  {
  if (this != addressof(that))  {
    if (that) emplace(std::move(*that));
    else reset();  
  }
  return *this;  
}

[2]{.pnum} Recommended practices: @_movable-box_@ should store only a T if either T models movable or is_nothrow_move_constructible_v<T> is true.

:::

Design Decisions

An alternative approach is to not have the @_movable-box_@ wrapper. Instead, we can just constrain single_view to only accept movable T. However, this is inconsistent with the rest of the range library.

Future Work

@_copyable-box_@ is not only used in single_view, but also used in lots of views that hold a function object. For example, transform_view stores the function inside @_copyable-box_@<F>. I think as view is no long required to be copyable, there should be no constraint for the function object F being copyable. And in fact, transform_view stores a base view: V base_. If base_ is not copyable, there is no point to have @_copyable-box_@<F>. This is the case for all other views that store the function objects. Potentially, the @_copyable-box_@ can be removed and replaced by the @_movable-box_@ that is proposed in this paper.