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// template<class In>
12// concept indirectly_readable;
13
14#include <concepts>
15#include <iterator>
16#include <type_traits>
17
18#include "read_write.h"
19
20template <class In>
21constexpr bool check_indirectly_readable() {
22 constexpr bool result = std::indirectly_readable<In>;
23 static_assert(std::indirectly_readable<In const> == result);
24 static_assert(std::indirectly_readable<In volatile> == result);
25 static_assert(std::indirectly_readable<In const volatile> == result);
26 static_assert(std::indirectly_readable<In const&> == result);
27 static_assert(std::indirectly_readable<In volatile&> == result);
28 static_assert(std::indirectly_readable<In const volatile&> == result);
29 static_assert(std::indirectly_readable<In const&&> == result);
30 static_assert(std::indirectly_readable<In volatile&&> == result);
31 static_assert(std::indirectly_readable<In const volatile&&> == result);
32 return result;
33}
34
35static_assert(!check_indirectly_readable<void*>());
36static_assert(!check_indirectly_readable<void const*>());
37static_assert(!check_indirectly_readable<void volatile*>());
38static_assert(!check_indirectly_readable<void const volatile*>());
39
40static_assert(check_indirectly_readable<int*>());
41static_assert(check_indirectly_readable<int const*>());
42static_assert(check_indirectly_readable<int volatile*>());
43static_assert(check_indirectly_readable<int const volatile*>());
44
45static_assert(check_indirectly_readable<value_type_indirection>());
46static_assert(check_indirectly_readable<element_type_indirection>());
47static_assert(check_indirectly_readable<proxy_indirection>());
48static_assert(check_indirectly_readable<read_only_indirection>());
49
50struct indirection_mismatch {
51 using value_type = int;
52 float& operator*() const;
53};
54static_assert(!std::same_as<std::iter_value_t<indirection_mismatch>, std::iter_reference_t<indirection_mismatch> > &&
55 check_indirectly_readable<indirection_mismatch>());
56static_assert(!check_indirectly_readable<missing_dereference>());
57
58// `iter_rvalue_reference_t` can't be missing unless the dereference operator is also missing.
59
60struct iter_move_mismatch {
61 using value_type = int;
62 value_type& operator*() const;
63
64 friend float& iter_move(iter_move_mismatch&);
65};
66static_assert(!check_indirectly_readable<iter_move_mismatch>());
67
68struct indirection_and_iter_move_mismatch {
69 using value_type = int;
70 float& operator*() const;
71
72 friend unsigned long long& iter_move(indirection_and_iter_move_mismatch&);
73};
74static_assert(!check_indirectly_readable<indirection_and_iter_move_mismatch>());
75
76struct missing_iter_value_t {
77 int operator*() const;
78};
79static_assert(!check_indirectly_readable<missing_iter_value_t>());
80
81struct unrelated_lvalue_ref_and_rvalue_ref {};
82
83struct iter_ref1 {};
84namespace std {
85template <>
86struct common_reference<iter_ref1&, iter_ref1&&> {};
87
88template <>
89struct common_reference<iter_ref1&&, iter_ref1&> {};
90} // namespace std
91static_assert(!std::common_reference_with<iter_ref1&, iter_ref1&&>);
92
93struct bad_iter_reference_t {
94 using value_type = int;
95 iter_ref1& operator*() const;
96};
97static_assert(!check_indirectly_readable<bad_iter_reference_t>());
98
99struct iter_ref2 {};
100struct iter_rvalue_ref {};
101
102struct unrelated_iter_ref_rvalue_and_iter_rvalue_ref_rvalue {
103 using value_type = iter_ref2;
104 iter_ref2& operator*() const;
105 friend iter_rvalue_ref&& iter_move(unrelated_iter_ref_rvalue_and_iter_rvalue_ref_rvalue);
106};
107static_assert(!check_indirectly_readable<unrelated_iter_ref_rvalue_and_iter_rvalue_ref_rvalue>());
108
109struct iter_ref3 {
110 operator iter_rvalue_ref() const;
111};
112namespace std {
113template <template <class> class XQual, template <class> class YQual>
114struct basic_common_reference<iter_ref3, iter_rvalue_ref, XQual, YQual> {
115 using type = iter_rvalue_ref;
116};
117template <template <class> class XQual, template <class> class YQual>
118struct basic_common_reference<iter_rvalue_ref, iter_ref3, XQual, YQual> {
119 using type = iter_rvalue_ref;
120};
121} // namespace std
122static_assert(std::common_reference_with<iter_ref3&&, iter_rvalue_ref&&>);
123
124struct different_reference_types_with_common_reference {
125 using value_type = iter_ref3;
126 iter_ref3& operator*() const;
127 friend iter_rvalue_ref&& iter_move(different_reference_types_with_common_reference);
128};
129static_assert(check_indirectly_readable<different_reference_types_with_common_reference>());
130
131struct iter_ref4 {
132 operator iter_rvalue_ref() const;
133};
134namespace std {
135template <template <class> class XQual, template <class> class YQual>
136struct basic_common_reference<iter_ref4, iter_rvalue_ref, XQual, YQual> {
137 using type = iter_rvalue_ref;
138};
139template <template <class> class XQual, template <class> class YQual>
140struct basic_common_reference<iter_rvalue_ref, iter_ref4, XQual, YQual> {
141 using type = iter_rvalue_ref;
142};
143
144template <>
145struct common_reference<iter_ref4 const&, iter_rvalue_ref&&> {};
146template <>
147struct common_reference<iter_rvalue_ref&&, iter_ref4 const&> {};
148} // namespace std
149static_assert(std::common_reference_with<iter_ref4&&, iter_rvalue_ref&&>);
150static_assert(!std::common_reference_with<iter_ref4 const&, iter_rvalue_ref&&>);
151
152struct different_reference_types_without_common_reference_to_const {
153 using value_type = iter_ref4;
154 iter_ref4& operator*() const;
155 friend iter_rvalue_ref&& iter_move(different_reference_types_without_common_reference_to_const);
156};
157static_assert(!check_indirectly_readable<different_reference_types_without_common_reference_to_const>());
158
159struct non_const_deref {
160 int& operator*();
161};
162static_assert(!check_indirectly_readable<non_const_deref>());
163
164struct not_referenceable {
165 using value_type = void;
166 void operator*() const;
167};
168static_assert(!std::indirectly_readable<not_referenceable>);
169
170struct legacy_output_iterator {
171 using value_type = void;
172 legacy_output_iterator& operator*();
173};
174
175static_assert(!std::indirectly_readable<legacy_output_iterator>);
176
177struct S {};
178static_assert(!std::indirectly_readable<S>);
179static_assert(!std::indirectly_readable<int S::*>);
180static_assert(!std::indirectly_readable<int (S::*)()>);
181static_assert(!std::indirectly_readable<int (S::*)() noexcept>);
182static_assert(!std::indirectly_readable<int (S::*)() &>);
183static_assert(!std::indirectly_readable<int (S::*)() & noexcept>);
184static_assert(!std::indirectly_readable<int (S::*)() &&>);
185static_assert(!std::indirectly_readable < int (S::*)() && noexcept >);
186static_assert(!std::indirectly_readable<int (S::*)() const>);
187static_assert(!std::indirectly_readable<int (S::*)() const noexcept>);
188static_assert(!std::indirectly_readable<int (S::*)() const&>);
189static_assert(!std::indirectly_readable<int (S::*)() const & noexcept>);
190static_assert(!std::indirectly_readable<int (S::*)() const&&>);
191static_assert(!std::indirectly_readable < int (S::*)() const&& noexcept >);
192static_assert(!std::indirectly_readable<int (S::*)() volatile>);
193static_assert(!std::indirectly_readable<int (S::*)() volatile noexcept>);
194static_assert(!std::indirectly_readable<int (S::*)() volatile&>);
195static_assert(!std::indirectly_readable<int (S::*)() volatile & noexcept>);
196static_assert(!std::indirectly_readable<int (S::*)() volatile&&>);
197static_assert(!std::indirectly_readable < int (S::*)() volatile&& noexcept >);
198

source code of libcxx/test/std/iterators/iterator.requirements/iterator.concepts/iterator.concept.readable/indirectly_readable.compile.pass.cpp