xref: /llvm-project/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/deref.pass.cpp (revision b2cc4b994e5fb85053b1acedec5ea0d1d42e5ec4)
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 
11 // constexpr decltype(auto) operator*() const;
12 
13 #include <array>
14 #include <cassert>
15 #include <ranges>
16 #include <tuple>
17 #include <utility>
18 
19 template <std::size_t N, class T, std::size_t Size>
testReference(T (& ts)[Size])20 constexpr void testReference(T (&ts)[Size]) {
21   auto ev = ts | std::views::elements<N>;
22   auto it = ev.begin();
23 
24   decltype(auto) result = *it;
25   using ExpectedType    = decltype(std::get<N>(ts[0]));
26   static_assert(std::is_same_v<decltype(result), ExpectedType>);
27 
28   if constexpr (std::is_reference_v<ExpectedType>) {
29     // tuple/array/pair
30     assert(&result == &std::get<N>(ts[0]));
31   } else {
32     // subrange
33     assert(result == std::get<N>(ts[0]));
34   }
35 }
36 
37 // LWG 3502 elements_view should not be allowed to return dangling references
38 template <std::size_t N, class T>
testValue(T t)39 constexpr void testValue(T t) {
40   auto ev = std::views::iota(0, 1) | std::views::transform([&t](int) { return t; }) | std::views::elements<N>;
41   auto it = ev.begin();
42 
43   decltype(auto) result = *it;
44   using ExpectedType    = std::remove_cvref_t<decltype(std::get<N>(t))>;
45   static_assert(std::is_same_v<decltype(result), ExpectedType>);
46 
47   assert(result == std::get<N>(t));
48 }
49 
test()50 constexpr bool test() {
51   // test tuple
52   {
53     std::tuple<int, short, long> ts[] = {{1, short{2}, 3}, {4, short{5}, 6}};
54     testReference<0>(ts);
55     testReference<1>(ts);
56     testReference<2>(ts);
57     testValue<0>(ts[0]);
58     testValue<1>(ts[0]);
59     testValue<2>(ts[0]);
60   }
61 
62   // test pair
63   {
64     std::pair<int, short> ps[] = {{1, short{2}}, {4, short{5}}};
65     testReference<0>(ps);
66     testReference<1>(ps);
67     testValue<0>(ps[0]);
68     testValue<1>(ps[0]);
69   }
70 
71   // test array
72   {
73     std::array<int, 3> arrs[] = {{1, 2, 3}, {3, 4, 5}};
74     testReference<0>(arrs);
75     testReference<1>(arrs);
76     testReference<2>(arrs);
77     testValue<0>(arrs[0]);
78     testValue<1>(arrs[0]);
79     testValue<2>(arrs[0]);
80   }
81 
82   // test subrange
83   {
84     int i                             = 5;
85     std::ranges::subrange<int*> srs[] = {{&i, &i}, {&i, &i}};
86     testReference<0>(srs);
87     testReference<1>(srs);
88     testValue<0>(srs[0]);
89     testValue<1>(srs[0]);
90   }
91 
92   return true;
93 }
94 
main(int,char **)95 int main(int, char**) {
96   test();
97   static_assert(test());
98 
99   return 0;
100 }
101