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