问题描述
以下代码在gcc上运行良好:
struct S {
int i,j;
auto operator<(const S& s) const {
return i < s.i;
};
};
std::vector<S> v;
std::make_heap(v.begin(),v.end());
但是当我切换到C ++ 20的范围算法时:
std::ranges::make_heap(v);
source>:14:27: error: no match for call to '(const std::ranges::__make_heap_fn) (std::vector<S>&)'
14 | std::ranges::make_heap(v);
|
^
似乎struct S
不能满足ranges::make_heap
的要求,但是我不知道它到底是什么,有人可以帮忙吗?
解决方法
std::ranges::make_heap
使用std::ranges::less
,它有一个约束条件:
与
std::less
不同,std::ranges::less
要求所有六个比较运算符<
,<=
,>
,>=
,==
和!=
有效(通过totally_ordered_with
约束)。
您的类型S
没有相等运算符;飞船运算符仅提供其他比较运算符。*
要解决此问题,请为您的类型提供一个operator==
:
constexpr auto operator==(const S& s) const {
return i == s.i;
}
Godbolt链接:https://godbolt.org/z/cGfrxs
* operator<=>
出于性能原因并不表示operator==
,因为operator==
可能会短路集合,而operator<=>
不会。但是,从https://en.cppreference.com/w/cpp/language/default_comparisons中,我们看到默认的operator<=>
也将隐式默认为operator==
。
我是怎么知道的?您代码的错误消息包括以下内容(由我整理和包装):
note: the expression 'is_invocable_v<_Fn,_Args ...> [with _Fn = std::ranges::less&; _Args = {value_type&,value_type&}]' evaluated to 'false' 338 | concept invocable = is_invocable_v<_Fn,_Args...>; | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
这意味着std::ranges::make_heap
发现不能为我们的类型调用std::ranges::less
。对向量的std::ranges::less
上的value_type
重复此错误消息调查,得出:
note: no operand of the disjunction is satisfied 123 | requires totally_ordered_with<_Tp,_Up> | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 124 | || __detail::__less_builtin_ptr_cmp<_Tp,_Up>
在这一点上,编译器正在努力告诉我们我们不满意totally_ordered_with
,这意味着该是时候阅读有关概念和std::ranges::less
的文档了。