what are the constraints for std::ranges::make_heap?

std::ranges::make_heap uses std::ranges::less, which has a constraint:

Unlike std::less, std::ranges::less requires all six comparison operators <, <=, >, >=, == and != to be valid (via the totally_ordered_with constraint).

Your type S does not have an equality operator; the spaceship operator only provides the other comparison operators.*

To fix this, provide an operator== for your type:

constexpr auto operator==(const S& s) const {
  return i == s.i;

Godbolt Link: https://godbolt.org/z/cGfrxs

* operator<=> does not imply operator== for performance reasons, as operator== can short circuit over collections whereas operator<=> cannot. However, from https://en.cppreference.com/w/cpp/language/default_comparisons , we see that a defaulted operator<=> will also implicitly default an operator==.

How did I figure this out? The error message for your code includes the following (trimmed and word wrapped by me):

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...>;
      |                         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~

This means that std::ranges::make_heap finds that it can’t call std::ranges::less for our type. Repeating this error message investigation for std::ranges::less on the value_type of the vector yields:

note: no operand of the disjunction is satisfied
  123 |       requires totally_ordered_with<_Tp, _Up>
      |                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  124 |         || __detail::__less_builtin_ptr_cmp<_Tp, _Up>

At this point, the compiler is trying hard to tell us that we aren’t satisfying totally_ordered_with, which means that it’s time to hit the documentation for the concept and for std::ranges::less.

CLICK HERE to find out more related problems solutions.

Leave a Comment

Your email address will not be published.

Scroll to Top