Search code examples
c++stlundefined-behavior

std::sort - is passing a faulty comparator undefined behavior?


Consider this code:

std::sort(vec.begin(), vec.end(),
    [](const Foo& lhs, const Foo& rhs) { return !(lhs < rhs); }
);

If lhs == rhs, both lambda(lhs, rhs) and lambda(rhs, lhs) will return true, which violates the requirement to provide strict weak ordering. However, does the standard explicitly mark passing such a comparator as undefined behavior?


Solution

  • Warning: extreme language-lawyering follows.

    The wording of the most recent draft of the standard puts it this way in [alg.sorting]p3:

    For all algorithms that take Compare, there is a version that uses operator< instead. That is, comp(*i, *j) != false defaults to *i < *j != false. For algorithms other than those described in 25.4.3, comp shall induce a strict weak ordering on the values.

    By using the word "shall", the standard is implicitly stating that violating it leads to undefined behavior.

    Whether this requires that the given function impose a SWO for all possible values or just for the values given to the algorithm is not clear from the standard. However, since the restriction is stated in a paragraph that is talking about those specific algorithms, it's not unreasonable to assume that it is refering to the range of values provided to the algorithm.

    Otherwise, the default operator< could not impose SWO for floats, thanks to NaN.