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

Implement ranges::common_view #1305

Merged
merged 18 commits into from
Nov 4, 2020
Merged
Show file tree
Hide file tree
Changes from 17 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
110 changes: 110 additions & 0 deletions stl/inc/ranges
Original file line number Diff line number Diff line change
Expand Up @@ -2059,6 +2059,116 @@ namespace ranges {

inline constexpr _Reverse_fn reverse;
} // namespace views

// CLASS TEMPLATE ranges::common_view
// clang-format off
template <view _Vw>
requires (!common_range<_Vw> && copyable<iterator_t<_Vw>>)
class common_view : public view_interface<common_view<_Vw>> {
// clang-format on
private:
/* [[no_unique_address]] */ _Vw _Base{};

public:
common_view() = default;
constexpr explicit common_view(_Vw _Base_) noexcept(is_nothrow_move_constructible_v<_Vw>) // strengthened
: _Base(_STD move(_Base_)) {}
// converting constructor template omitted per LWG-3405

_NODISCARD constexpr _Vw base() const& noexcept(
is_nothrow_copy_constructible_v<_Vw>) /* strengthened */ requires copy_constructible<_Vw> {
return _Base;
}
_NODISCARD constexpr _Vw base() && noexcept(is_nothrow_move_constructible_v<_Vw>) /* strengthened */ {
return _STD move(_Base);
}

_NODISCARD constexpr auto begin() noexcept(
noexcept(_RANGES begin(_Base)) && is_nothrow_move_constructible_v<iterator_t<_Vw>>) /* strengthened */ {
if constexpr (random_access_range<_Vw> && sized_range<_Vw>) {
return _RANGES begin(_Base);
} else {
return common_iterator<iterator_t<_Vw>, sentinel_t<_Vw>>{_RANGES begin(_Base)};
}
}

_NODISCARD constexpr auto begin() const noexcept(
noexcept(_RANGES begin(_Base))
&& is_nothrow_move_constructible_v<iterator_t<const _Vw>>) /* strengthened */ requires range<const _Vw> {
if constexpr (random_access_range<const _Vw> && sized_range<const _Vw>) {
return _RANGES begin(_Base);
} else {
return common_iterator<iterator_t<const _Vw>, sentinel_t<const _Vw>>{_RANGES begin(_Base)};
}
}

_NODISCARD constexpr auto end() {
if constexpr (random_access_range<_Vw> && sized_range<_Vw>) {
return _RANGES begin(_Base) + _RANGES size(_Base);
} else {
return common_iterator<iterator_t<_Vw>, sentinel_t<_Vw>>{_RANGES end(_Base)};
}
}

_NODISCARD constexpr auto end() const requires range<const _Vw> {
if constexpr (random_access_range<const _Vw> && sized_range<const _Vw>) {
return _RANGES begin(_Base) + _RANGES size(_Base);
} else {
return common_iterator<iterator_t<const _Vw>, sentinel_t<const _Vw>>{_RANGES end(_Base)};
}
}

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

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

namespace views {
// VARIABLE views::common
class _Common_fn : public _Pipe::_Base<_Common_fn> {
private:
enum class _St { _None, _All, _Common };

template <class _Rng>
_NODISCARD static _CONSTEVAL _Choice_t<_St> _Choose() noexcept {
if constexpr (common_range<_Rng>) {
return {_St::_All, noexcept(views::all(_STD declval<_Rng>()))};
} else if constexpr (copyable<iterator_t<_Rng>>) {
return {_St::_Common, noexcept(common_view{_STD declval<_Rng>()})};
} else {
return {_St::_None};
}
}

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

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

inline constexpr _Common_fn common;
} // namespace views
} // namespace ranges

namespace views = ranges::views;
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ tests\P0896R4_ranges_test_machinery
tests\P0896R4_ranges_to_address
tests\P0896R4_stream_iterators
tests\P0896R4_views_all
tests\P0896R4_views_common
tests\P0896R4_views_drop
tests\P0896R4_views_empty
tests\P0896R4_views_filter
Expand Down
1 change: 1 addition & 0 deletions tests/std/tests/P0896R4_ranges_range_machinery/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ STATIC_ASSERT(test_cpo(ranges::data));
STATIC_ASSERT(test_cpo(ranges::cdata));

STATIC_ASSERT(test_cpo(ranges::views::all));
STATIC_ASSERT(test_cpo(ranges::views::common));
STATIC_ASSERT(test_cpo(ranges::views::drop));
STATIC_ASSERT(test_cpo(ranges::views::filter));
STATIC_ASSERT(test_cpo(ranges::views::reverse));
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P0896R4_views_common/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 ..\strict_concepts_matrix.lst
Loading