xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.elements/begin.pass.cpp (revision 94461822c75d5080bf648f86552f7a59b76905c9)
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 auto begin() requires (!simple-view<V>)
12*94461822SHui Xie //  constexpr auto begin() const requires range<const V>
13*94461822SHui Xie 
14*94461822SHui Xie #include <cassert>
15*94461822SHui Xie #include <concepts>
16*94461822SHui Xie #include <ranges>
17*94461822SHui Xie #include <tuple>
18*94461822SHui Xie #include <utility>
19*94461822SHui Xie 
20*94461822SHui Xie #include "types.h"
21*94461822SHui Xie 
22*94461822SHui Xie template <class T>
23*94461822SHui Xie concept HasConstBegin = requires(const T ct) { ct.begin(); };
24*94461822SHui Xie 
25*94461822SHui Xie template <class T>
26*94461822SHui Xie concept HasBegin = requires(T t) { t.begin(); };
27*94461822SHui Xie 
28*94461822SHui Xie template <class T>
29*94461822SHui Xie concept HasConstAndNonConstBegin =
30*94461822SHui Xie     HasConstBegin<T> &&
31*94461822SHui Xie     // because const begin and non-const begin returns different types (iterator<true>, iterator<false>)
32*94461822SHui Xie     requires(T t, const T ct) { requires !std::same_as<decltype(t.begin()), decltype(ct.begin())>; };
33*94461822SHui Xie 
34*94461822SHui Xie template <class T>
35*94461822SHui Xie concept HasOnlyNonConstBegin = HasBegin<T> && !HasConstBegin<T>;
36*94461822SHui Xie 
37*94461822SHui Xie template <class T>
38*94461822SHui Xie concept HasOnlyConstBegin = HasConstBegin<T> && !HasConstAndNonConstBegin<T>;
39*94461822SHui Xie 
40*94461822SHui Xie struct NoConstBeginView : TupleBufferView {
41*94461822SHui Xie   using TupleBufferView::TupleBufferView;
beginNoConstBeginView42*94461822SHui Xie   constexpr std::tuple<int>* begin() { return buffer_; }
endNoConstBeginView43*94461822SHui Xie   constexpr std::tuple<int>* end() { return buffer_ + size_; }
44*94461822SHui Xie };
45*94461822SHui Xie 
46*94461822SHui Xie // simple-view<V>
47*94461822SHui Xie static_assert(HasOnlyConstBegin<std::ranges::elements_view<SimpleCommon, 0>>);
48*94461822SHui Xie 
49*94461822SHui Xie // !simple-view<V> && range<const V>
50*94461822SHui Xie static_assert(HasConstAndNonConstBegin<std::ranges::elements_view<NonSimpleCommon, 0>>);
51*94461822SHui Xie 
52*94461822SHui Xie // !range<const V>
53*94461822SHui Xie static_assert(HasOnlyNonConstBegin<std::ranges::elements_view<NoConstBeginView, 0>>);
54*94461822SHui Xie 
test()55*94461822SHui Xie constexpr bool test() {
56*94461822SHui Xie   std::tuple<int> buffer[] = {{1}, {2}};
57*94461822SHui Xie   {
58*94461822SHui Xie     // underlying iterator should be pointing to the first element
59*94461822SHui Xie     auto ev   = std::views::elements<0>(buffer);
60*94461822SHui Xie     auto iter = ev.begin();
61*94461822SHui Xie     assert(&(*iter) == &std::get<0>(buffer[0]));
62*94461822SHui Xie   }
63*94461822SHui Xie 
64*94461822SHui Xie   {
65*94461822SHui Xie     // underlying range models simple-view
66*94461822SHui Xie     auto v = std::views::elements<0>(SimpleCommon{buffer});
67*94461822SHui Xie     static_assert(std::is_same_v<decltype(v.begin()), decltype(std::as_const(v).begin())>);
68*94461822SHui Xie     assert(v.begin() == std::as_const(v).begin());
69*94461822SHui Xie     auto&& r = *std::as_const(v).begin();
70*94461822SHui Xie     assert(&r == &std::get<0>(buffer[0]));
71*94461822SHui Xie   }
72*94461822SHui Xie 
73*94461822SHui Xie   {
74*94461822SHui Xie     // underlying const R is not a range
75*94461822SHui Xie     auto v   = std::views::elements<0>(NoConstBeginView{buffer});
76*94461822SHui Xie     auto&& r = *v.begin();
77*94461822SHui Xie     assert(&r == &std::get<0>(buffer[0]));
78*94461822SHui Xie   }
79*94461822SHui Xie 
80*94461822SHui Xie   return true;
81*94461822SHui Xie }
82*94461822SHui Xie 
main(int,char **)83*94461822SHui Xie int main(int, char**) {
84*94461822SHui Xie   test();
85*94461822SHui Xie   static_assert(test());
86*94461822SHui Xie 
87*94461822SHui Xie   return 0;
88*94461822SHui Xie }
89