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

P2278R4: views::as_const #3234

Merged
merged 8 commits into from
Dec 15, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
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
132 changes: 132 additions & 0 deletions stl/inc/ranges
Original file line number Diff line number Diff line change
Expand Up @@ -5046,6 +5046,138 @@ namespace ranges {
_EXPORT_STD inline constexpr _Reverse_fn reverse;
} // namespace views

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

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

constexpr explicit as_const_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(_RANGES cbegin(_Range))) // strengthened
requires (!_Simple_view<_Vw>)
{
return _RANGES cbegin(_Range);
}

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

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

_NODISCARD constexpr auto end() const noexcept(noexcept(_RANGES cend(_Range))) // strengthened
requires range<const _Vw>
{
return _RANGES cend(_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_const_view(_Rng&&) -> as_const_view<views::all_t<_Rng>>;

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

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

class _As_const_fn : public _Pipe::_Base<_As_const_fn> {
private:
enum class _St { _None, _All, _Reconstruct_span, _Reconstruct_ref, _Ref, _As_const };

template <class>
static constexpr bool _Can_reconstruct_ref_view_v = false;

template <class _Ty>
requires constant_range<const _Ty>
static constexpr bool _Can_reconstruct_ref_view_v<ref_view<_Ty>> = true;

template <class _Rng>
_NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept {
using _Ty = remove_cvref_t<_Rng>;

if constexpr (constant_range<views::all_t<_Rng>>) {
return {_St::_All, noexcept(views::all(_STD declval<_Rng>()))};
} else if constexpr (_Is_span_v<_Ty>) {
return {_St::_Reconstruct_span, true};
} else if constexpr (_Can_reconstruct_ref_view_v<_Ty>) {
return {_St::_Reconstruct_ref, noexcept(ref_view{_STD as_const(_STD declval<_Rng>().base())})};
} else if constexpr (is_lvalue_reference_v<_Rng> && constant_range<const _Ty> && !view<_Ty>) {
return {_St::_Ref, noexcept(ref_view{_STD as_const(_STD declval<_Rng>())})};
} else if constexpr (_Can_as_const<_Rng>) {
return {_St::_As_const, noexcept(as_const_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) {
using _Ty = remove_cvref_t<_Rng>;
constexpr _St _Strat = _Choice<_Rng>._Strategy;

if constexpr (_Strat == _St::_All) {
return views::all(_STD forward<_Rng>(_Range));
} else if constexpr (_Strat == _St::_Reconstruct_span) {
return span<const typename _Ty::element_type, _Ty::extent>{_STD forward<_Rng>(_Range)};
} else if constexpr (_Strat == _St::_Reconstruct_ref) {
return ref_view{_STD as_const(_STD forward<_Rng>(_Range).base())};
} else if constexpr (_Strat == _St::_Ref) {
return ref_view{_STD as_const(_STD forward<_Rng>(_Range))};
} else if constexpr (_Strat == _St::_As_const) {
return as_const_view{_STD forward<_Rng>(_Range)};
} else {
static_assert(_Always_false<_Rng>, "Should be unreachable");
}
}
};

_EXPORT_STD inline constexpr _As_const_fn as_const;
} // namespace views
#endif // _HAS_CXX23

template <class _Tuple, size_t _Index>
concept _Has_tuple_element = //
requires(_Tuple __t) {
Expand Down
2 changes: 1 addition & 1 deletion stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,6 @@
// P2186R2 Removing Garbage Collection Support
// P2273R3 constexpr unique_ptr
// P2278R4 cbegin Should Always Return A Constant Iterator
// (missing views::as_const)
// P2291R3 constexpr Integral <charconv>
// P2302R4 ranges::contains, ranges::contains_subrange
// P2321R2 zip
Expand Down Expand Up @@ -1673,6 +1672,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_const 202207L
#define __cpp_lib_ranges_as_rvalue 202207L
#define __cpp_lib_ranges_chunk 202202L
#define __cpp_lib_ranges_chunk_by 202202L
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,7 @@ tests\P2278R4_basic_const_iterator
tests\P2278R4_const_span
tests\P2278R4_ranges_const_iterator_machinery
tests\P2278R4_ranges_const_range_machinery
tests\P2278R4_views_as_const
tests\P2302R4_ranges_alg_contains
tests\P2302R4_ranges_alg_contains_subrange
tests\P2321R2_proxy_reference
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P2278R4_views_as_const/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\concepts_latest_matrix.lst
Loading