Vir*_*leo 2 c++ c++20 std-ranges
我正在尝试使引用包装器与异构搜索一起使用,并使其符合范围。这是我想要工作的片段:
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
}
Run Code Online (Sandbox Code Playgroud)
异构搜索对于经典std算法来说工作得很好(对于它们来说,实现<和就足够了==。现在,ranges它们有更严格的要求,所以我尝试通过以下方式实现强排序操作:
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; }
};
Run Code Online (Sandbox Code Playgroud)
然而,这会导致许多编译错误,这些错误似乎是在警告indirect_strict_weak_order概念strict_weak_order未得到解决。我不明白为什么他们没有解决 - 我们有很强的秩序,并且据我了解,间接部分得到了适当的支持。我缺少什么?
这是编译器资源管理器示例:https ://godbolt.org/z/8xaWfah9b 。
异构搜索对于经典
std算法来说工作得很好(对于它们来说,实现<和就足够了==。现在,ranges人们有更严格的要求
version默认用于比较,它对比较类型的语法和语义要求比rangesversion更严格,但您仍然可以作为仅要求表达式有效的比较器传递ranges::lessstdstd::lesslhs < rhs
const auto found = ra::binary_search(num_refs, 2, std::less{});
Run Code Online (Sandbox Code Playgroud)
范围算法不适用于异构比较。使用投影:
std::ranges::binary_search(num_refs, 2, {}, [](ref<const addressable> r) {
return r.get().address;
});
Run Code Online (Sandbox Code Playgroud)
在这种特定情况下,您不能使用ranges::less{}(2, ref<const addressable>(...)),因为ranges::less需要两个参数totally_ordered彼此在一起,这要求它们有一个common_reference. const int&和之间没有公共引用,除非您添加从到 的const ref<const addressable>&转换。ref<const addressable>const int&