104 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 V base() const & requires copy_constructible<V> { return base_; }12// constexpr V base() && { return std::move(base_); }13 14#include <cassert>15#include <ranges>16#include <type_traits>17#include <utility>18 19#include "MoveOnly.h"20 21struct View : std::ranges::view_base {22 int i;23 int* begin() const;24 int* end() const;25};26 27struct MoveOnlyView : View {28 MoveOnly mo;29};30 31template <class T>32concept HasBase = requires(T&& t) { std::forward<T>(t).base(); };33 34static_assert(HasBase<std::ranges::split_view<View, View> const&>);35static_assert(HasBase<std::ranges::split_view<View, View>&&>);36 37static_assert(!HasBase<std::ranges::split_view<MoveOnlyView, View> const&>);38static_assert(HasBase<std::ranges::split_view<MoveOnlyView, View>&&>);39 40constexpr bool test() {41 // const &42 {43 const std::ranges::split_view<View, View> sv{View{{}, 5}, View{{}, 0}};44 std::same_as<View> decltype(auto) v = sv.base();45 assert(v.i == 5);46 }47 48 // &49 {50 std::ranges::split_view<View, View> sv{View{{}, 5}, View{{}, 0}};51 std::same_as<View> decltype(auto) v = sv.base();52 assert(v.i == 5);53 }54 55 // &&56 {57 std::ranges::split_view<View, View> sv{View{{}, 5}, View{{}, 0}};58 std::same_as<View> decltype(auto) v = std::move(sv).base();59 assert(v.i == 5);60 }61 62 // const &&63 {64 std::ranges::split_view<View, View> sv{View{{}, 5}, View{{}, 0}};65 std::same_as<View> decltype(auto) v = std::move(sv).base();66 assert(v.i == 5);67 }68 69 // move only70 {71 std::ranges::split_view<MoveOnlyView, View> sv{MoveOnlyView{{}, 5}, View{{}, 0}};72 std::same_as<MoveOnlyView> decltype(auto) v = std::move(sv).base();73 assert(v.mo.get() == 5);74 }75 76 // LWG 3590 split_view::base() const & is overconstrained77 {78 struct CopyCtorButNotAssignable : std::ranges::view_base {79 int i;80 constexpr CopyCtorButNotAssignable(int ii) : i(ii) {}81 constexpr CopyCtorButNotAssignable(const CopyCtorButNotAssignable&) = default;82 constexpr CopyCtorButNotAssignable(CopyCtorButNotAssignable&&) = default;83 constexpr CopyCtorButNotAssignable& operator=(CopyCtorButNotAssignable&&) = default;84 constexpr CopyCtorButNotAssignable& operator=(const CopyCtorButNotAssignable&) = delete;85 constexpr int* begin() const { return nullptr; }86 constexpr int* end() const { return nullptr; }87 };88 static_assert(std::copy_constructible<CopyCtorButNotAssignable>);89 static_assert(!std::copyable<CopyCtorButNotAssignable>);90 const std::ranges::split_view<CopyCtorButNotAssignable, CopyCtorButNotAssignable> sv{91 CopyCtorButNotAssignable{5}, CopyCtorButNotAssignable{5}};92 std::same_as<CopyCtorButNotAssignable> decltype(auto) v = sv.base();93 assert(v.i == 5);94 }95 96 return true;97}98 99int main(int, char**) {100 test();101 static_assert(test());102 return 0;103}104