Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

P2446R2: views::as_rvalue #3008

Merged
merged 13 commits into from
Aug 12, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Implement views::as_rvalue
JMazurkiewicz committed Aug 9, 2022
commit db75a9da1e38bc64f93776465eb6fd5004c51f9d
118 changes: 118 additions & 0 deletions stl/inc/ranges
Original file line number Diff line number Diff line change
@@ -1627,6 +1627,124 @@ namespace ranges {
using all_t = decltype(all(_STD declval<_Rng>()));
} // namespace views

#if _HAS_CXX23
template <input_range _Vw>
requires view<_Vw>
class as_rvalue_view : public view_interface<as_rvalue_view<_Vw>> {
private:
/* [[no_unique_address]] */ _Vw _Range{};

template <range _Rng>
static constexpr bool _Is_end_nothrow_v = noexcept(move_sentinel{_RANGES end(_STD declval<_Rng>())});

template <common_range _Rng>
static constexpr bool _Is_end_nothrow_v<_Rng> = noexcept(move_iterator{_RANGES end(_STD declval<_Rng>())});

public:
// clang-format off
as_rvalue_view() requires default_initializable<_Vw> = default;
// clang-format on

constexpr explicit as_rvalue_view(_Vw _Range_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened
: _Range(_STD move(_Range_)) {}

_NODISCARD constexpr _Vw base() const& noexcept(is_nothrow_copy_constructible_v<_Vw>) // strengthened
requires copy_constructible<_Vw> {
return _Range;
}

_NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ {
return _STD move(_Range);
}

_NODISCARD constexpr auto begin() noexcept(noexcept(move_iterator{_RANGES begin(_Range)})) // strengthened
requires(!_Simple_view<_Vw>) {
return move_iterator{_RANGES begin(_Range)};
}

_NODISCARD constexpr auto begin() const noexcept(noexcept(move_iterator{_RANGES begin(_Range)})) // strengthened
requires range<const _Vw> {
return move_iterator{_RANGES begin(_Range)};
}

_NODISCARD constexpr auto end() noexcept(_Is_end_nothrow_v<_Vw>) // strengthened
requires(!_Simple_view<_Vw>) {
if constexpr (common_range<_Vw>) {
return move_iterator{_RANGES end(_Range)};
} else {
return move_sentinel{_RANGES end(_Range)};
}
}

_NODISCARD constexpr auto end() const noexcept(_Is_end_nothrow_v<const _Vw>) // strengthened
requires range<const _Vw> {
if constexpr (common_range<const _Vw>) {
return move_iterator{_RANGES end(_Range)};
} else {
return move_sentinel{_RANGES end(_Range)};
}
}

_NODISCARD constexpr auto size() noexcept(noexcept(_RANGES size(_Range))) // strengthened
requires sized_range<_Vw> {
return _RANGES size(_Range);
}

_NODISCARD constexpr auto size() const noexcept(noexcept(_RANGES size(_Range))) // strengthened
requires sized_range<const _Vw> {
return _RANGES size(_Range);
}
};

template <class _Rng>
as_rvalue_view(_Rng&&) -> as_rvalue_view<views::all_t<_Rng>>;

template <class _Rng>
inline constexpr bool enable_borrowed_range<as_rvalue_view<_Rng>> = enable_borrowed_range<_Rng>;

namespace views {
template <class _Rng>
concept _Can_as_rvalue = requires(_Rng&& __r) {
as_rvalue_view{static_cast<_Rng&&>(__r)};
};

struct _As_rvalue_fn : _Pipe::_Base<_As_rvalue_fn> {
private:
enum class _St { _None, _All, _As_rvalue };

template <class _Rng>
_NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept {
if constexpr (same_as<range_rvalue_reference_t<_Rng>, range_reference_t<_Rng>>) {
return {_St::_All, noexcept(views::all(_STD declval<_Rng>()))};
} else if constexpr (_Can_as_rvalue<_Rng>) {
return {_St::_As_rvalue, noexcept(as_rvalue_view{_STD declval<_Rng>()})};
} else {
return {_St::_None};
}
}

template <class _Rng>
static constexpr _Choice_t<_St> _Choice = _Choose<_Rng>();

public:
template <viewable_range _Rng>
requires(_Choice<_Rng>._Strategy != _St::_None)
_NODISCARD constexpr auto operator()(_Rng&& _Range) const noexcept(_Choice<_Rng>._No_throw) {
constexpr _St _Strat = _Choice<_Rng>._Strategy;
if constexpr (_Strat == _St::_All) {
return views::all(_STD forward<_Rng>(_Range));
} else if constexpr (_Strat == _St::_As_rvalue) {
return as_rvalue_view{_STD forward<_Rng>(_Range)};
} else {
static_assert(_Always_false<_Rng>, "Should be unreachable");
}
}
};

inline constexpr _As_rvalue_fn as_rvalue;
} // namespace views
#endif // _HAS_CXX23

template <input_range _Vw, indirect_unary_predicate<iterator_t<_Vw>> _Pr>
requires view<_Vw> && is_object_v<_Pr>
class filter_view : public _Cached_position_t<forward_range<_Vw>, _Vw, filter_view<_Vw, _Pr>> {
2 changes: 2 additions & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
@@ -329,6 +329,7 @@
// P2442R1 Windowing Range Adaptors: views::chunk, views::slide
// P2443R1 views::chunk_by
// P2445R1 forward_like()
// P2446R2 views::as_rvalue
// P2499R0 string_view Range Constructor Should Be explicit
// P2549R0 unexpected<E>::error()

@@ -1511,6 +1512,7 @@ _EMIT_STL_ERROR(STL1004, "C++98 unexpected() is incompatible with C++23 unexpect

#ifdef __cpp_lib_concepts
#define __cpp_lib_out_ptr 202106L
#define __cpp_lib_ranges_as_rvalue 202207L
#define __cpp_lib_ranges_chunk 202202L
#define __cpp_lib_ranges_chunk_by 202202L
#define __cpp_lib_ranges_contains 202207L
Original file line number Diff line number Diff line change
@@ -1454,6 +1454,20 @@ STATIC_ASSERT(__cpp_lib_ranges == 202110L);
#endif
#endif

#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
#ifndef __cpp_lib_ranges_as_rvalue
#error __cpp_lib_ranges_as_rvalue is not defined
#elif __cpp_lib_ranges_as_rvalue != 202207L
#error __cpp_lib_ranges_as_rvalue is not 202207L
#else
STATIC_ASSERT(__cpp_lib_ranges_as_rvalue == 202207L);
#endif
#else
#ifdef __cpp_lib_ranges_as_rvalue
#error __cpp_lib_ranges_as_rvalue is defined
#endif
#endif

#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
#ifndef __cpp_lib_ranges_chunk
#error __cpp_lib_ranges_chunk is not defined