126 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++1710 11// constexpr View base() const& requires copy_constructible<_View>;12// constexpr View base() &&;13 14#include <ranges>15 16#include <cassert>17#include <string_view>18#include <utility>19#include "types.h"20 21struct MoveOnlyView : std::ranges::view_base {22 std::string_view view_;23 constexpr MoveOnlyView() = default;24 constexpr MoveOnlyView(const char* ptr) : view_(ptr) {}25 constexpr MoveOnlyView(std::string_view v) : view_(v) {}26 constexpr MoveOnlyView(MoveOnlyView&&) = default;27 constexpr MoveOnlyView& operator=(MoveOnlyView&&) = default;28 constexpr std::string_view::const_iterator begin() const { return view_.begin(); }29 constexpr std::string_view::const_iterator end() const { return view_.end(); }30 constexpr bool operator==(MoveOnlyView rhs) const { return view_ == rhs.view_; }31};32static_assert( std::ranges::view<MoveOnlyView>);33static_assert( std::ranges::contiguous_range<MoveOnlyView>);34static_assert(!std::copyable<MoveOnlyView>);35 36struct ViewWithInitTracking : std::ranges::view_base {37 enum class InitializedBy {38 Copy,39 Move,40 Invalid41 };42 43 std::string_view v_;44 InitializedBy initialized_by = InitializedBy::Invalid;45 constexpr ViewWithInitTracking(std::string_view v) : v_(v) {}46 47 constexpr auto begin() const { return v_.begin(); }48 constexpr auto end() const { return v_.end(); }49 50 constexpr ViewWithInitTracking(const ViewWithInitTracking& rhs) : v_(rhs.v_) { initialized_by = InitializedBy::Copy; }51 constexpr ViewWithInitTracking(ViewWithInitTracking&& rhs) : v_(rhs.v_) { initialized_by = InitializedBy::Move; }52 constexpr ViewWithInitTracking& operator=(const ViewWithInitTracking& rhs) = default;53 constexpr ViewWithInitTracking& operator=(ViewWithInitTracking&& rhs) = default;54 constexpr bool operator==(const ViewWithInitTracking& rhs) const { return v_ == rhs.v_; }55};56 57template <class View>58concept CanCallBase = requires(View v) { std::forward<View>(v).base(); };59 60static_assert( CanCallBase<std::ranges::lazy_split_view<MoveOnlyView, ForwardView>&&>);61static_assert(!CanCallBase<std::ranges::lazy_split_view<MoveOnlyView, ForwardView>&>);62static_assert(!CanCallBase<std::ranges::lazy_split_view<MoveOnlyView, ForwardView> const &>);63static_assert(!CanCallBase<std::ranges::lazy_split_view<MoveOnlyView, ForwardView> const &&>);64 65constexpr bool test() {66 using View = ViewWithInitTracking;67 68 // Copyable input -- both lvalue and rvalue overloads of `base` are available.69 {70 // Non-const lvalue.71 {72 View str{"abc def"};73 std::ranges::lazy_split_view<View, std::string_view> v(str, " ");74 75 std::same_as<View> decltype(auto) result = v.base();76 assert(result == str);77 assert(result.initialized_by == View::InitializedBy::Copy);78 }79 80 // Const lvalue.81 {82 View str{"abc def"};83 const std::ranges::lazy_split_view<View, std::string_view> v(str, " ");84 85 std::same_as<View> decltype(auto) result = v.base();86 assert(result == str);87 assert(result.initialized_by == View::InitializedBy::Copy);88 }89 90 // Non-const rvalue.91 {92 View str{"abc def"};93 std::ranges::lazy_split_view<View, std::string_view> v(str, " ");94 95 std::same_as<View> decltype(auto) result = std::move(v).base();96 assert(result == str);97 assert(result.initialized_by == View::InitializedBy::Move);98 }99 100 // Const rvalue.101 {102 View str{"abc def"};103 const std::ranges::lazy_split_view<View, std::string_view> v(str, " ");104 105 std::same_as<View> decltype(auto) result = std::move(v).base();106 assert(result == str);107 assert(result.initialized_by == View::InitializedBy::Copy);108 }109 }110 111 // Move-only input -- only the rvalue overload of `base` is available.112 {113 std::ranges::lazy_split_view<MoveOnlyView, ForwardView> v;114 assert(std::move(v).base() == MoveOnlyView());115 }116 117 return true;118}119 120int main(int, char**) {121 test();122 static_assert(test());123 124 return 0;125}126