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
19template <std::size_t N, class T, std::size_t Size>
20constexpr 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
38template <std::size_t N, class T>
39constexpr 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
50constexpr 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>(t: ts[0]);
58 testValue<1>(t: ts[0]);
59 testValue<2>(t: ts[0]);
60 }
61
62 // test pair
63 {
64 std::pair<int, short> ps[] = {{1, short{2}}, {4, short{5}}};
65 testReference<0>(ts&: ps);
66 testReference<1>(ts&: ps);
67 testValue<0>(t: ps[0]);
68 testValue<1>(t: ps[0]);
69 }
70
71 // test array
72 {
73 std::array<int, 3> arrs[] = {{1, 2, 3}, {3, 4, 5}};
74 testReference<0>(ts&: arrs);
75 testReference<1>(ts&: arrs);
76 testReference<2>(ts&: arrs);
77 testValue<0>(t: arrs[0]);
78 testValue<1>(t: arrs[0]);
79 testValue<2>(t: 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
95int main(int, char**) {
96 test();
97 static_assert(test());
98
99 return 0;
100}
101

source code of libcxx/test/std/ranges/range.adaptors/range.elements/iterator/deref.pass.cpp