I am trying to make reference wrappers work with heterogeneous search, and make it ranges-compliant. Here is the snippet I want to work:
struct addressable { int address; };
template <typename T>
struct ref : std::reference_wrapper<T> {
// comparisons for heterogeneous search
}
template <typename T>
ref<T> wrap_ref(T& value) { return {value}; }
int main() {
const std::vector<addressable> nums { {1}, {2}, {3}, {4}, {5}, {6} };
ref_vec<const addressable> num_refs;
for (const auto& num : nums) { num_refs.push_back(wrap_ref(num)); }
const auto found = std::ranges::binary_search(num_refs, 2); // doesn't work
}
The heterogeneous search is working fine for classic std
algorithms (for them it is enough to implement <
and ==
. Now, ranges
ones have more stringent requirements, so I tried implementing strong ordering operations in the following manner:
template <typename T>
struct ref : std::reference_wrapper<T> {
auto operator<=>(const ref<T>& other) const {
return std::reference_wrapper<T>::get().address <=> other.get().address;
}
bool operator==(const ref<T>& other) const {
return std::reference_wrapper<T>::get().address == other.get().address;
}
// heterogeneous comparisons
friend auto operator<=>(const ref<T>& l, const int r) { return l.get().address <=> r; }
friend auto operator<=>(const int l, const ref<T>& r) { return l <=> r.get().address; }
friend bool operator==(const ref<T>& l, const int r) { return l.get().address == r; }
friend bool operator==(const int l, const ref<T>& r) { return l == r.get().address; }
};
This, however, leads to a number of compilation errors, which seem to warn about indirect_strict_weak_order
and strict_weak_order
concepts not being resolved. I do not understand why aren't they resolved - we have strong order, and references are, to my understanding, properly supported for the indirect part. What am I missing?
Here is compiler explorer example: https://godbolt.org/z/8xaWfah9b.