100 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++17, c++2010 11// <ranges>12 13// constexpr View base() const& requires copy_constructible<View>;14// constexpr View base() &&;15 16#include <ranges>17 18#include <cassert>19#include <concepts>20#include <utility>21 22struct Range : std::ranges::view_base {23 constexpr explicit Range(int* b, int* e) : begin_(b), end_(e) {}24 constexpr Range(Range const& other) : begin_(other.begin_), end_(other.end_), wasCopyInitialized(true) {}25 constexpr Range(Range&& other) : begin_(other.begin_), end_(other.end_), wasMoveInitialized(true) {}26 Range& operator=(Range const&) = default;27 Range& operator=(Range&&) = default;28 constexpr int* begin() const { return begin_; }29 constexpr int* end() const { return end_; }30 31 int* begin_;32 int* end_;33 bool wasCopyInitialized = false;34 bool wasMoveInitialized = false;35};36 37static_assert(std::ranges::view<Range>);38static_assert(std::ranges::forward_range<Range>);39 40struct Pred {41 bool operator()(int, int) const;42};43 44struct NonCopyableRange : std::ranges::view_base {45 explicit NonCopyableRange(int*, int*);46 NonCopyableRange(NonCopyableRange const&) = delete;47 NonCopyableRange(NonCopyableRange&&) = default;48 NonCopyableRange& operator=(NonCopyableRange const&) = default;49 NonCopyableRange& operator=(NonCopyableRange&&) = default;50 int* begin() const;51 int* end() const;52};53 54static_assert(!std::copy_constructible<NonCopyableRange>);55 56template <typename T>57concept CanCallBaseOn = requires(T t) { std::forward<T>(t).base(); };58 59constexpr bool test() {60 int buff[] = {1, 2, 3, 4};61 62 // Check the const& overload63 {64 Range range(buff, buff + 4);65 std::ranges::chunk_by_view<Range, Pred> const view(range, Pred{});66 std::same_as<Range> decltype(auto) result = view.base();67 assert(result.wasCopyInitialized);68 assert(result.begin() == buff);69 assert(result.end() == buff + 4);70 }71 72 // Check the && overload73 {74 Range range(buff, buff + 4);75 std::ranges::chunk_by_view<Range, Pred> view(range, Pred{});76 std::same_as<Range> decltype(auto) result = std::move(view).base();77 assert(result.wasMoveInitialized);78 assert(result.begin() == buff);79 assert(result.end() == buff + 4);80 }81 82 // Ensure the const& overload is not considered when the base is not copy-constructible83 {84 static_assert(!CanCallBaseOn<std::ranges::chunk_by_view<NonCopyableRange, Pred> const&>);85 static_assert(!CanCallBaseOn<std::ranges::chunk_by_view<NonCopyableRange, Pred>&>);86 static_assert(!CanCallBaseOn<std::ranges::chunk_by_view<NonCopyableRange, Pred> const&&>);87 static_assert(CanCallBaseOn<std::ranges::chunk_by_view<NonCopyableRange, Pred>&&>);88 static_assert(CanCallBaseOn<std::ranges::chunk_by_view<NonCopyableRange, Pred>>);89 }90 91 return true;92}93 94int main(int, char**) {95 test();96 static_assert(test());97 98 return 0;99}100