1e53c461bSKonstantin Varlamov //===----------------------------------------------------------------------===// 2e53c461bSKonstantin Varlamov // 3e53c461bSKonstantin Varlamov // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e53c461bSKonstantin Varlamov // See https://llvm.org/LICENSE.txt for license information. 5e53c461bSKonstantin Varlamov // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e53c461bSKonstantin Varlamov // 7e53c461bSKonstantin Varlamov //===----------------------------------------------------------------------===// 8e53c461bSKonstantin Varlamov 9e53c461bSKonstantin Varlamov // UNSUPPORTED: c++03, c++11, c++14, c++17 10e53c461bSKonstantin Varlamov 11e53c461bSKonstantin Varlamov // constexpr View base() const& requires copy_constructible<_View>; 12e53c461bSKonstantin Varlamov // constexpr View base() &&; 13e53c461bSKonstantin Varlamov 14e53c461bSKonstantin Varlamov #include <ranges> 15e53c461bSKonstantin Varlamov 16e53c461bSKonstantin Varlamov #include <cassert> 17e53c461bSKonstantin Varlamov #include <string_view> 18e53c461bSKonstantin Varlamov #include <utility> 19e53c461bSKonstantin Varlamov #include "types.h" 20e53c461bSKonstantin Varlamov 21e53c461bSKonstantin Varlamov struct MoveOnlyView : std::ranges::view_base { 22e53c461bSKonstantin Varlamov std::string_view view_; 23e53c461bSKonstantin Varlamov constexpr MoveOnlyView() = default; 24e53c461bSKonstantin Varlamov constexpr MoveOnlyView(const char* ptr) : view_(ptr) {} 25e53c461bSKonstantin Varlamov constexpr MoveOnlyView(std::string_view v) : view_(v) {} 26e53c461bSKonstantin Varlamov constexpr MoveOnlyView(MoveOnlyView&&) = default; 27e53c461bSKonstantin Varlamov constexpr MoveOnlyView& operator=(MoveOnlyView&&) = default; 28*a845b5b4SLouis Dionne constexpr std::string_view::const_iterator begin() const { return view_.begin(); } 29*a845b5b4SLouis Dionne constexpr std::string_view::const_iterator end() const { return view_.end(); } 30e53c461bSKonstantin Varlamov constexpr bool operator==(MoveOnlyView rhs) const { return view_ == rhs.view_; } 31e53c461bSKonstantin Varlamov }; 32e53c461bSKonstantin Varlamov static_assert( std::ranges::view<MoveOnlyView>); 33e53c461bSKonstantin Varlamov static_assert( std::ranges::contiguous_range<MoveOnlyView>); 34e53c461bSKonstantin Varlamov static_assert(!std::copyable<MoveOnlyView>); 35e53c461bSKonstantin Varlamov 36e53c461bSKonstantin Varlamov struct ViewWithInitTracking : std::ranges::view_base { 37e53c461bSKonstantin Varlamov enum class InitializedBy { 38e53c461bSKonstantin Varlamov Copy, 39e53c461bSKonstantin Varlamov Move, 40e53c461bSKonstantin Varlamov Invalid 41e53c461bSKonstantin Varlamov }; 42e53c461bSKonstantin Varlamov 43e53c461bSKonstantin Varlamov std::string_view v_; 44e53c461bSKonstantin Varlamov InitializedBy initialized_by = InitializedBy::Invalid; 45e53c461bSKonstantin Varlamov constexpr ViewWithInitTracking(std::string_view v) : v_(v) {} 46e53c461bSKonstantin Varlamov 47e53c461bSKonstantin Varlamov constexpr auto begin() const { return v_.begin(); } 48e53c461bSKonstantin Varlamov constexpr auto end() const { return v_.end(); } 49e53c461bSKonstantin Varlamov 50e53c461bSKonstantin Varlamov constexpr ViewWithInitTracking(const ViewWithInitTracking& rhs) : v_(rhs.v_) { initialized_by = InitializedBy::Copy; } 51e53c461bSKonstantin Varlamov constexpr ViewWithInitTracking(ViewWithInitTracking&& rhs) : v_(rhs.v_) { initialized_by = InitializedBy::Move; } 52e53c461bSKonstantin Varlamov constexpr ViewWithInitTracking& operator=(const ViewWithInitTracking& rhs) = default; 53e53c461bSKonstantin Varlamov constexpr ViewWithInitTracking& operator=(ViewWithInitTracking&& rhs) = default; 54e53c461bSKonstantin Varlamov constexpr bool operator==(const ViewWithInitTracking& rhs) const { return v_ == rhs.v_; } 55e53c461bSKonstantin Varlamov }; 56e53c461bSKonstantin Varlamov 57e53c461bSKonstantin Varlamov template <class View> 58e53c461bSKonstantin Varlamov concept CanCallBase = requires(View v) { std::forward<View>(v).base(); }; 59e53c461bSKonstantin Varlamov 60e53c461bSKonstantin Varlamov static_assert( CanCallBase<std::ranges::lazy_split_view<MoveOnlyView, ForwardView>&&>); 61e53c461bSKonstantin Varlamov static_assert(!CanCallBase<std::ranges::lazy_split_view<MoveOnlyView, ForwardView>&>); 62e53c461bSKonstantin Varlamov static_assert(!CanCallBase<std::ranges::lazy_split_view<MoveOnlyView, ForwardView> const &>); 63e53c461bSKonstantin Varlamov static_assert(!CanCallBase<std::ranges::lazy_split_view<MoveOnlyView, ForwardView> const &&>); 64e53c461bSKonstantin Varlamov 65e53c461bSKonstantin Varlamov constexpr bool test() { 66e53c461bSKonstantin Varlamov using View = ViewWithInitTracking; 67e53c461bSKonstantin Varlamov 68e53c461bSKonstantin Varlamov // Copyable input -- both lvalue and rvalue overloads of `base` are available. 69e53c461bSKonstantin Varlamov { 70e53c461bSKonstantin Varlamov // Non-const lvalue. 71e53c461bSKonstantin Varlamov { 724051cac2SLouis Dionne View str{"abc def"}; 73e53c461bSKonstantin Varlamov std::ranges::lazy_split_view<View, std::string_view> v(str, " "); 74e53c461bSKonstantin Varlamov 75e53c461bSKonstantin Varlamov std::same_as<View> decltype(auto) result = v.base(); 76e53c461bSKonstantin Varlamov assert(result == str); 77e53c461bSKonstantin Varlamov assert(result.initialized_by == View::InitializedBy::Copy); 78e53c461bSKonstantin Varlamov } 79e53c461bSKonstantin Varlamov 80e53c461bSKonstantin Varlamov // Const lvalue. 81e53c461bSKonstantin Varlamov { 824051cac2SLouis Dionne View str{"abc def"}; 83e53c461bSKonstantin Varlamov const std::ranges::lazy_split_view<View, std::string_view> v(str, " "); 84e53c461bSKonstantin Varlamov 85e53c461bSKonstantin Varlamov std::same_as<View> decltype(auto) result = v.base(); 86e53c461bSKonstantin Varlamov assert(result == str); 87e53c461bSKonstantin Varlamov assert(result.initialized_by == View::InitializedBy::Copy); 88e53c461bSKonstantin Varlamov } 89e53c461bSKonstantin Varlamov 90e53c461bSKonstantin Varlamov // Non-const rvalue. 91e53c461bSKonstantin Varlamov { 924051cac2SLouis Dionne View str{"abc def"}; 93e53c461bSKonstantin Varlamov std::ranges::lazy_split_view<View, std::string_view> v(str, " "); 94e53c461bSKonstantin Varlamov 95e53c461bSKonstantin Varlamov std::same_as<View> decltype(auto) result = std::move(v).base(); 96e53c461bSKonstantin Varlamov assert(result == str); 97e53c461bSKonstantin Varlamov assert(result.initialized_by == View::InitializedBy::Move); 98e53c461bSKonstantin Varlamov } 99e53c461bSKonstantin Varlamov 100e53c461bSKonstantin Varlamov // Const rvalue. 101e53c461bSKonstantin Varlamov { 1024051cac2SLouis Dionne View str{"abc def"}; 103e53c461bSKonstantin Varlamov const std::ranges::lazy_split_view<View, std::string_view> v(str, " "); 104e53c461bSKonstantin Varlamov 105e53c461bSKonstantin Varlamov std::same_as<View> decltype(auto) result = std::move(v).base(); 106e53c461bSKonstantin Varlamov assert(result == str); 107e53c461bSKonstantin Varlamov assert(result.initialized_by == View::InitializedBy::Copy); 108e53c461bSKonstantin Varlamov } 109e53c461bSKonstantin Varlamov } 110e53c461bSKonstantin Varlamov 111e53c461bSKonstantin Varlamov // Move-only input -- only the rvalue overload of `base` is available. 112e53c461bSKonstantin Varlamov { 113e53c461bSKonstantin Varlamov std::ranges::lazy_split_view<MoveOnlyView, ForwardView> v; 114e53c461bSKonstantin Varlamov assert(std::move(v).base() == MoveOnlyView()); 115e53c461bSKonstantin Varlamov } 116e53c461bSKonstantin Varlamov 117e53c461bSKonstantin Varlamov return true; 118e53c461bSKonstantin Varlamov } 119e53c461bSKonstantin Varlamov 120e53c461bSKonstantin Varlamov int main(int, char**) { 121e53c461bSKonstantin Varlamov test(); 122e53c461bSKonstantin Varlamov static_assert(test()); 123e53c461bSKonstantin Varlamov 124e53c461bSKonstantin Varlamov return 0; 125e53c461bSKonstantin Varlamov } 126