1*a2c6a119SHui Xie //===----------------------------------------------------------------------===//
2*a2c6a119SHui Xie //
3*a2c6a119SHui Xie // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*a2c6a119SHui Xie // See https://llvm.org/LICENSE.txt for license information.
5*a2c6a119SHui Xie // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*a2c6a119SHui Xie //
7*a2c6a119SHui Xie //===----------------------------------------------------------------------===//
8*a2c6a119SHui Xie
9*a2c6a119SHui Xie // UNSUPPORTED: c++03, c++11, c++14, c++17
10*a2c6a119SHui Xie
11*a2c6a119SHui Xie // constexpr V base() const & requires copy_constructible<V> { return base_; }
12*a2c6a119SHui Xie // constexpr V base() && { return std::move(base_); }
13*a2c6a119SHui Xie
14*a2c6a119SHui Xie #include <cassert>
15*a2c6a119SHui Xie #include <ranges>
16*a2c6a119SHui Xie #include <type_traits>
17*a2c6a119SHui Xie #include <utility>
18*a2c6a119SHui Xie
19*a2c6a119SHui Xie #include "MoveOnly.h"
20*a2c6a119SHui Xie #include "types.h"
21*a2c6a119SHui Xie
22*a2c6a119SHui Xie struct View : std::ranges::view_interface<View> {
23*a2c6a119SHui Xie int i;
24*a2c6a119SHui Xie int* begin() const;
25*a2c6a119SHui Xie int* end() const;
26*a2c6a119SHui Xie };
27*a2c6a119SHui Xie
28*a2c6a119SHui Xie struct MoveOnlyView : View {
29*a2c6a119SHui Xie MoveOnly mo;
30*a2c6a119SHui Xie };
31*a2c6a119SHui Xie
32*a2c6a119SHui Xie template <class T>
33*a2c6a119SHui Xie concept HasBase = requires(T&& t) { std::forward<T>(t).base(); };
34*a2c6a119SHui Xie
35*a2c6a119SHui Xie struct Pred {
operator ()Pred36*a2c6a119SHui Xie constexpr bool operator()(int i) const { return i > 5; }
37*a2c6a119SHui Xie };
38*a2c6a119SHui Xie
39*a2c6a119SHui Xie static_assert(HasBase<std::ranges::take_while_view<View, Pred> const&>);
40*a2c6a119SHui Xie static_assert(HasBase<std::ranges::take_while_view<View, Pred>&&>);
41*a2c6a119SHui Xie
42*a2c6a119SHui Xie static_assert(!HasBase<std::ranges::take_while_view<MoveOnlyView, Pred> const&>);
43*a2c6a119SHui Xie static_assert(HasBase<std::ranges::take_while_view<MoveOnlyView, Pred>&&>);
44*a2c6a119SHui Xie
test()45*a2c6a119SHui Xie constexpr bool test() {
46*a2c6a119SHui Xie // const &
47*a2c6a119SHui Xie {
48*a2c6a119SHui Xie const std::ranges::take_while_view<View, Pred> twv{View{{}, 5}, {}};
49*a2c6a119SHui Xie std::same_as<View> decltype(auto) v = twv.base();
50*a2c6a119SHui Xie assert(v.i == 5);
51*a2c6a119SHui Xie }
52*a2c6a119SHui Xie
53*a2c6a119SHui Xie // &
54*a2c6a119SHui Xie {
55*a2c6a119SHui Xie std::ranges::take_while_view<View, Pred> twv{View{{}, 5}, {}};
56*a2c6a119SHui Xie std::same_as<View> decltype(auto) v = twv.base();
57*a2c6a119SHui Xie assert(v.i == 5);
58*a2c6a119SHui Xie }
59*a2c6a119SHui Xie
60*a2c6a119SHui Xie // &&
61*a2c6a119SHui Xie {
62*a2c6a119SHui Xie std::ranges::take_while_view<View, Pred> twv{View{{}, 5}, {}};
63*a2c6a119SHui Xie std::same_as<View> decltype(auto) v = std::move(twv).base();
64*a2c6a119SHui Xie assert(v.i == 5);
65*a2c6a119SHui Xie }
66*a2c6a119SHui Xie
67*a2c6a119SHui Xie // const &&
68*a2c6a119SHui Xie {
69*a2c6a119SHui Xie const std::ranges::take_while_view<View, Pred> twv{View{{}, 5}, {}};
70*a2c6a119SHui Xie std::same_as<View> decltype(auto) v = std::move(twv).base();
71*a2c6a119SHui Xie assert(v.i == 5);
72*a2c6a119SHui Xie }
73*a2c6a119SHui Xie
74*a2c6a119SHui Xie // move only
75*a2c6a119SHui Xie {
76*a2c6a119SHui Xie std::ranges::take_while_view<MoveOnlyView, Pred> twv{MoveOnlyView{{}, 5}, {}};
77*a2c6a119SHui Xie std::same_as<MoveOnlyView> decltype(auto) v = std::move(twv).base();
78*a2c6a119SHui Xie assert(v.mo.get() == 5);
79*a2c6a119SHui Xie }
80*a2c6a119SHui Xie return true;
81*a2c6a119SHui Xie }
82*a2c6a119SHui Xie
main(int,char **)83*a2c6a119SHui Xie int main(int, char**) {
84*a2c6a119SHui Xie test();
85*a2c6a119SHui Xie static_assert(test());
86*a2c6a119SHui Xie return 0;
87*a2c6a119SHui Xie }
88