|
16 | 16 |
|
17 | 17 | #include <array> |
18 | 18 | #include <cassert> |
| 19 | +#include <cstddef> |
19 | 20 | #include <string> |
20 | 21 | #include <string_view> |
| 22 | +#include <type_traits> |
21 | 23 | #include <utility> |
22 | 24 | #include <vector> |
23 | 25 |
|
24 | 26 | #include "../types.h" |
25 | 27 |
|
| 28 | +struct ProxyInt { |
| 29 | + int& val; |
| 30 | +}; |
| 31 | + |
| 32 | +class ExtraProxyInt { |
| 33 | +public: |
| 34 | + constexpr ExtraProxyInt(ProxyInt i) : val(i.val) {} |
| 35 | + constexpr ExtraProxyInt(int i) : val(i) {} |
| 36 | + |
| 37 | + constexpr int get() const { return val; } |
| 38 | + |
| 39 | +private: |
| 40 | + int val; |
| 41 | +}; |
| 42 | + |
| 43 | +template <template <class> class TQual, template <class> class UQual> |
| 44 | +struct std::basic_common_reference<ProxyInt, int, TQual, UQual> { |
| 45 | + using type = ExtraProxyInt; |
| 46 | +}; |
| 47 | + |
| 48 | +template <template <class> class TQual, template <class> class UQual> |
| 49 | +struct std::basic_common_reference<int, ProxyInt, TQual, UQual> { |
| 50 | + using type = ExtraProxyInt; |
| 51 | +}; |
| 52 | + |
| 53 | +static_assert(std::common_reference_with<int&, ProxyInt>); |
| 54 | +static_assert(std::common_reference_with<int&, ExtraProxyInt>); |
| 55 | + |
| 56 | +class ProxyIter { |
| 57 | +public: |
| 58 | + using value_type = int; |
| 59 | + using difference_type = std::ptrdiff_t; |
| 60 | + |
| 61 | + constexpr ProxyIter() : ptr_(nullptr) {} |
| 62 | + constexpr explicit ProxyIter(int* p) : ptr_(p) {} |
| 63 | + |
| 64 | + constexpr ProxyInt operator*() const { return ProxyInt{*ptr_}; } |
| 65 | + |
| 66 | + constexpr ProxyIter& operator++() { |
| 67 | + ++ptr_; |
| 68 | + return *this; |
| 69 | + } |
| 70 | + |
| 71 | + constexpr ProxyIter operator++(int) { |
| 72 | + ProxyIter tmp = *this; |
| 73 | + ++ptr_; |
| 74 | + return tmp; |
| 75 | + } |
| 76 | + |
| 77 | + constexpr bool operator==(const ProxyIter& other) const { return ptr_ == other.ptr_; } |
| 78 | + |
| 79 | +private: |
| 80 | + int* ptr_; |
| 81 | +}; |
| 82 | + |
| 83 | +static_assert(std::forward_iterator<ProxyIter>); |
| 84 | + |
26 | 85 | constexpr bool test() { |
27 | 86 | { // Result of `operator*` is (maybe const) lvalue reference |
28 | 87 | using V = std::ranges::owning_view<std::vector<std::string>>; |
@@ -133,6 +192,28 @@ constexpr bool test() { |
133 | 192 | } |
134 | 193 | } |
135 | 194 |
|
| 195 | + { // Result of `operator*` is type different from range_reference_t<InnerRng> and range_reference_t<Pattern> |
| 196 | + using Inner = std::vector<int>; |
| 197 | + using V = std::vector<Inner>; |
| 198 | + using Pattern = std::ranges::subrange<ProxyIter, ProxyIter>; |
| 199 | + using JWV = std::ranges::join_with_view<std::ranges::owning_view<V>, std::ranges::owning_view<Pattern>>; |
| 200 | + |
| 201 | + static_assert(!std::same_as<std::ranges::range_reference_t<V>, std::ranges::range_reference_t<JWV>>); |
| 202 | + static_assert(!std::same_as<std::ranges::range_reference_t<Pattern>, std::ranges::range_reference_t<JWV>>); |
| 203 | + |
| 204 | + std::array<int, 2> pattern = {-1, -1}; |
| 205 | + Pattern pattern_as_subrange(ProxyIter{pattern.data()}, ProxyIter{pattern.data() + pattern.size()}); |
| 206 | + |
| 207 | + JWV jwv(V{Inner{1, 1}, Inner{2, 2}, Inner{3, 3}}, std::move(pattern_as_subrange)); |
| 208 | + |
| 209 | + auto it = jwv.begin(); |
| 210 | + std::same_as<ExtraProxyInt> decltype(auto) v_ref = *it; |
| 211 | + assert(v_ref.get() == 1); |
| 212 | + std::ranges::advance(it, 7); |
| 213 | + std::same_as<ExtraProxyInt> decltype(auto) pattern_ref = *std::as_const(it); |
| 214 | + assert(pattern_ref.get() == -1); |
| 215 | + } |
| 216 | + |
136 | 217 | return true; |
137 | 218 | } |
138 | 219 |
|
|
0 commit comments