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 iter_ref1 {
82 iter_ref1(const iter_ref1&) = delete;
83 iter_ref1(iter_ref1&&) = delete;
84};
85
86struct bad_iter_reference_t {
87 using value_type = int;
88 iter_ref1& operator*() const;
89};
90static_assert(!check_indirectly_readable<bad_iter_reference_t>());
91
92struct iter_ref2 {};
93struct iter_rvalue_ref {};
94
95struct unrelated_iter_ref_rvalue_and_iter_rvalue_ref_rvalue {
96 using value_type = iter_ref2;
97 iter_ref2& operator*() const;
98 friend iter_rvalue_ref&& iter_move(unrelated_iter_ref_rvalue_and_iter_rvalue_ref_rvalue);
99};
100static_assert(!check_indirectly_readable<unrelated_iter_ref_rvalue_and_iter_rvalue_ref_rvalue>());
101
102struct iter_ref3 {
103 operator iter_rvalue_ref() const;
104};
105
106template <template <class> class XQual, template <class> class YQual>
107struct std::basic_common_reference<iter_ref3, iter_rvalue_ref, XQual, YQual> {
108 using type = iter_rvalue_ref;
109};
110template <template <class> class XQual, template <class> class YQual>
111struct std::basic_common_reference<iter_rvalue_ref, iter_ref3, XQual, YQual> {
112 using type = iter_rvalue_ref;
113};
114
115static_assert(std::common_reference_with<iter_ref3&&, iter_rvalue_ref&&>);
116
117struct different_reference_types_with_common_reference {
118 using value_type = iter_ref3;
119 iter_ref3& operator*() const;
120 friend iter_rvalue_ref&& iter_move(different_reference_types_with_common_reference);
121};
122static_assert(check_indirectly_readable<different_reference_types_with_common_reference>());
123
124struct iter_ref4 {
125 operator iter_rvalue_ref();
126};
127
128static_assert(std::common_reference_with<iter_ref4&&, iter_rvalue_ref&&>);
129static_assert(!std::common_reference_with<iter_ref4 const&, iter_rvalue_ref&&>);
130
131struct different_reference_types_without_common_reference_to_const {
132 using value_type = iter_ref4;
133 iter_ref4& operator*() const;
134 friend iter_rvalue_ref&& iter_move(different_reference_types_without_common_reference_to_const);
135};
136static_assert(!check_indirectly_readable<different_reference_types_without_common_reference_to_const>());
137
138struct non_const_deref {
139 int& operator*();
140};
141static_assert(!check_indirectly_readable<non_const_deref>());
142
143struct not_referenceable {
144 using value_type = void;
145 void operator*() const;
146};
147static_assert(!std::indirectly_readable<not_referenceable>);
148
149struct legacy_output_iterator {
150 using value_type = void;
151 legacy_output_iterator& operator*();
152};
153
154static_assert(!std::indirectly_readable<legacy_output_iterator>);
155
156struct S {};
157static_assert(!std::indirectly_readable<S>);
158static_assert(!std::indirectly_readable<int S::*>);
159static_assert(!std::indirectly_readable<int (S::*)()>);
160static_assert(!std::indirectly_readable<int (S::*)() noexcept>);
161static_assert(!std::indirectly_readable<int (S::*)() &>);
162static_assert(!std::indirectly_readable<int (S::*)() & noexcept>);
163static_assert(!std::indirectly_readable<int (S::*)() &&>);
164static_assert(!std::indirectly_readable < int (S::*)() && noexcept >);
165static_assert(!std::indirectly_readable<int (S::*)() const>);
166static_assert(!std::indirectly_readable<int (S::*)() const noexcept>);
167static_assert(!std::indirectly_readable<int (S::*)() const&>);
168static_assert(!std::indirectly_readable<int (S::*)() const & noexcept>);
169static_assert(!std::indirectly_readable<int (S::*)() const&&>);
170static_assert(!std::indirectly_readable < int (S::*)() const&& noexcept >);
171static_assert(!std::indirectly_readable<int (S::*)() volatile>);
172static_assert(!std::indirectly_readable<int (S::*)() volatile noexcept>);
173static_assert(!std::indirectly_readable<int (S::*)() volatile&>);
174static_assert(!std::indirectly_readable<int (S::*)() volatile & noexcept>);
175static_assert(!std::indirectly_readable<int (S::*)() volatile&&>);
176static_assert(!std::indirectly_readable < int (S::*)() volatile&& noexcept >);
177

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