Skip to content
Open
Show file tree
Hide file tree
Changes from 6 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
8 changes: 6 additions & 2 deletions libcxx/include/__ranges/common_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@ class common_view : public view_interface<common_view<_View>> {

_LIBCPP_HIDE_FROM_ABI constexpr _View base() && { return std::move(__base_); }

_LIBCPP_HIDE_FROM_ABI constexpr auto begin() {
_LIBCPP_HIDE_FROM_ABI constexpr auto begin()
requires(!__simple_view<_View>)
{
if constexpr (random_access_range<_View> && sized_range<_View>)
return ranges::begin(__base_);
else
Expand All @@ -74,7 +76,9 @@ class common_view : public view_interface<common_view<_View>> {
return common_iterator<iterator_t<const _View>, sentinel_t<const _View>>(ranges::begin(__base_));
}

_LIBCPP_HIDE_FROM_ABI constexpr auto end() {
_LIBCPP_HIDE_FROM_ABI constexpr auto end()
requires(!__simple_view<_View>)
{
if constexpr (random_access_range<_View> && sized_range<_View>)
return ranges::begin(__base_) + ranges::size(__base_);
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ constexpr bool test() {
assert(begin == std::ranges::begin(view));
}

{
NonSimpleNonCommonView view{buf, buf + 8};
std::ranges::common_view<NonSimpleNonCommonView> common(view);
static_assert(!std::is_same_v<decltype(common.begin()), decltype(std::as_const(common).begin())>);
}

return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ constexpr bool test() {
assert(base(end) == buf + 8);
}

{
NonSimpleNonCommonView view{buf, buf + 8};
std::ranges::common_view<NonSimpleNonCommonView> common(view);
static_assert(!std::is_same_v<decltype(common.end()), decltype(std::as_const(common).end())>);
}

return true;
}

Expand Down
83 changes: 64 additions & 19 deletions libcxx/test/std/ranges/range.adaptors/range.common.view/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
#include "test_iterators.h"

struct DefaultConstructibleView : std::ranges::view_base {
int* begin_ = nullptr;
int* end_ = nullptr;
int* begin_ = nullptr;
int* end_ = nullptr;
explicit DefaultConstructibleView() = default;
constexpr int *begin() const { return begin_; }
constexpr int* begin() const { return begin_; }
constexpr auto end() const { return sentinel_wrapper<int*>(end_); }
};
static_assert(std::ranges::view<DefaultConstructibleView>);
Expand All @@ -26,21 +26,21 @@ static_assert(std::default_initializable<DefaultConstructibleView>);
struct MoveOnlyView : std::ranges::view_base {
int* begin_;
int* end_;
constexpr explicit MoveOnlyView(int* b, int* e) : begin_(b), end_(e) { }
constexpr MoveOnlyView(MoveOnlyView&&) = default;
constexpr explicit MoveOnlyView(int* b, int* e) : begin_(b), end_(e) {}
constexpr MoveOnlyView(MoveOnlyView&&) = default;
constexpr MoveOnlyView& operator=(MoveOnlyView&&) = default;
constexpr int *begin() const { return begin_; }
constexpr int* begin() const { return begin_; }
constexpr auto end() const { return sentinel_wrapper<int*>(end_); }
};
static_assert( std::ranges::view<MoveOnlyView>);
static_assert( std::ranges::contiguous_range<MoveOnlyView>);
static_assert(std::ranges::view<MoveOnlyView>);
static_assert(std::ranges::contiguous_range<MoveOnlyView>);
static_assert(!std::copyable<MoveOnlyView>);

struct CopyableView : std::ranges::view_base {
int* begin_;
int* end_;
constexpr explicit CopyableView(int* b, int* e) : begin_(b), end_(e) { }
constexpr int *begin() const { return begin_; }
constexpr explicit CopyableView(int* b, int* e) : begin_(b), end_(e) {}
constexpr int* begin() const { return begin_; }
constexpr auto end() const { return sentinel_wrapper<int*>(end_); }
};
static_assert(std::ranges::view<CopyableView>);
Expand All @@ -50,7 +50,7 @@ using ForwardIter = forward_iterator<int*>;
struct SizedForwardView : std::ranges::view_base {
int* begin_;
int* end_;
constexpr explicit SizedForwardView(int* b, int* e) : begin_(b), end_(e) { }
constexpr explicit SizedForwardView(int* b, int* e) : begin_(b), end_(e) {}
constexpr auto begin() const { return forward_iterator<int*>(begin_); }
constexpr auto end() const { return sized_sentinel<forward_iterator<int*>>(forward_iterator<int*>(end_)); }
};
Expand All @@ -62,9 +62,11 @@ using RandomAccessIter = random_access_iterator<int*>;
struct SizedRandomAccessView : std::ranges::view_base {
int* begin_;
int* end_;
constexpr explicit SizedRandomAccessView(int* b, int* e) : begin_(b), end_(e) { }
constexpr explicit SizedRandomAccessView(int* b, int* e) : begin_(b), end_(e) {}
constexpr auto begin() const { return random_access_iterator<int*>(begin_); }
constexpr auto end() const { return sized_sentinel<random_access_iterator<int*>>(random_access_iterator<int*>(end_)); }
constexpr auto end() const {
return sized_sentinel<random_access_iterator<int*>>(random_access_iterator<int*>(end_));
}
};
static_assert(std::ranges::view<SizedRandomAccessView>);
static_assert(std::ranges::random_access_range<SizedRandomAccessView>);
Expand All @@ -73,21 +75,64 @@ static_assert(std::ranges::sized_range<SizedRandomAccessView>);
struct CommonView : std::ranges::view_base {
int* begin_;
int* end_;
constexpr explicit CommonView(int* b, int* e) : begin_(b), end_(e) { }
constexpr int *begin() const { return begin_; }
constexpr int *end() const { return end_; }
constexpr explicit CommonView(int* b, int* e) : begin_(b), end_(e) {}
constexpr int* begin() const { return begin_; }
constexpr int* end() const { return end_; }
};
static_assert(std::ranges::view<CommonView>);
static_assert(std::ranges::common_range<CommonView>);

struct NonCommonView : std::ranges::view_base {
int* begin_;
int* end_;
constexpr explicit NonCommonView(int* b, int* e) : begin_(b), end_(e) { }
constexpr int *begin() const { return begin_; }
constexpr explicit NonCommonView(int* b, int* e) : begin_(b), end_(e) {}
constexpr int* begin() const { return begin_; }
constexpr auto end() const { return sentinel_wrapper<int*>(end_); }
};
static_assert( std::ranges::view<NonCommonView>);
static_assert(std::ranges::view<NonCommonView>);
static_assert(!std::ranges::common_range<NonCommonView>);

template <class T>
concept HasConstBegin = requires(const T& ct) { ct.begin(); };

template <class T>
concept HasBegin = requires(T& t) { t.begin(); };

template <class T>
concept HasConstAndNonConstBegin = HasConstBegin<T> && requires(T& t, const T& ct) {
requires !std::same_as<decltype(t.begin()), decltype(ct.begin())>;
};

template <class T>
concept HasOnlyNonConstBegin = HasBegin<T> && !HasConstBegin<T>;

template <class T>
concept HasOnlyConstBegin = HasConstBegin<T> && !HasConstAndNonConstBegin<T>;

template <bool Simple>
struct NonCommonBaseView : std::ranges::view_base {
int* begin_;
int* end_;
constexpr explicit NonCommonBaseView(int* b, int* e) : begin_(b), end_(e) {}
constexpr auto begin() const { return static_cast<const int*>(begin_); }
constexpr auto end() const { return sentinel_wrapper<const int*>(end_); }
constexpr int* begin()
requires(!Simple)
{
return begin_;
}
constexpr auto end()
requires(!Simple)
{
return sentinel_wrapper<int*>(end_);
}
};
using NonSimpleNonCommonView = NonCommonBaseView<false>;

static_assert(!HasOnlyNonConstBegin<std::ranges::common_view<NonSimpleNonCommonView>>);
static_assert(!HasOnlyConstBegin<std::ranges::common_view<NonSimpleNonCommonView>>);
static_assert(HasConstAndNonConstBegin<std::ranges::common_view<NonSimpleNonCommonView>>);
static_assert(HasConstBegin<std::ranges::common_view<NonSimpleNonCommonView> const>);
static_assert(HasOnlyConstBegin<std::ranges::common_view<NonSimpleNonCommonView> const>);

#endif // TEST_STD_RANGES_RANGE_ADAPTORS_RANGE_COMMON_VIEW_TYPES_H
Loading