Skip to content

Commit e55c077

Browse files
committed
Test when result of operator* is type different from range_reference_t<InnerRng> and range_reference_t<Pattern>
Related comment: #65536 (comment)
1 parent f6f603d commit e55c077

File tree

1 file changed

+81
-0
lines changed
  • libcxx/test/std/ranges/range.adaptors/range.join.with/range.join.with.iterator

1 file changed

+81
-0
lines changed

libcxx/test/std/ranges/range.adaptors/range.join.with/range.join.with.iterator/deref.pass.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,72 @@
1616

1717
#include <array>
1818
#include <cassert>
19+
#include <cstddef>
1920
#include <string>
2021
#include <string_view>
22+
#include <type_traits>
2123
#include <utility>
2224
#include <vector>
2325

2426
#include "../types.h"
2527

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+
2685
constexpr bool test() {
2786
{ // Result of `operator*` is (maybe const) lvalue reference
2887
using V = std::ranges::owning_view<std::vector<std::string>>;
@@ -133,6 +192,28 @@ constexpr bool test() {
133192
}
134193
}
135194

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+
136217
return true;
137218
}
138219

0 commit comments

Comments
 (0)