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> |
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> |
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 | |
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>(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 | |
95 | int main(int, char**) { |
96 | test(); |
97 | static_assert(test()); |
98 | |
99 | return 0; |
100 | } |
101 | |