Why will stdsort crash if the comparison function is not as operator ?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
std::sort does not require your comparison function to literally be operator<, but it does require the comparator to behave like a strict weak ordering. If that rule is broken, the result is undefined behavior, which means the sort may appear to work, produce garbage, loop unexpectedly, or crash.
The Real Requirement Is Strict Weak Ordering
Many explanations say the comparator must be "like operator<." That is shorthand, not the actual rule. The comparator can use any logic you want as long as it defines a consistent ordering.
At minimum, a valid comparator should satisfy these ideas:
- '
comp(a, a)must be false' - if
comp(a, b)is true, thencomp(b, a)must be false - if
comp(a, b)andcomp(b, c)are true, thencomp(a, c)must also be true
This is what lets std::sort partition and rearrange the range safely. The algorithm assumes those properties while moving iterators around and comparing elements repeatedly.
A Comparator That Looks Reasonable but Is Wrong
A very common bug is using <= instead of <.
This comparator is invalid because comp(2, 2) returns true. That breaks irreflexivity immediately.
It may still appear to work on a small input, but the behavior is undefined. std::sort is allowed to assume the comparator is valid, so once the assumption is false the implementation has no obligation to remain sane.
Why Undefined Behavior Can Turn Into a Crash
Sorting implementations such as introsort rely on the comparator to split the range consistently. If the comparator contradicts itself, internal loops may fail to make progress as expected.
That can lead to:
- bad partitions
- unexpected recursion patterns
- invalid assumptions inside optimized code paths
The C++ standard does not say "std::sort must detect bad comparators and throw an error." It says your program has undefined behavior if the comparator does not meet the requirements.
So the crash is not because the comparator differs from operator<. The crash happens because the comparator violates the contract that std::sort depends on.
A Correct Custom Comparator
Here is a valid custom comparator that sorts strings by length and then alphabetically:
This comparator is not the same as plain operator<, but it is still valid because it defines a consistent strict weak ordering.
Another Subtle Failure: Nontransitive Logic
Comparators can also fail in more interesting ways than <=. Suppose someone writes a rule based on the last digit only:
This is actually fine as an ordering if you are happy treating values with the same last digit as equivalent.
But if someone writes inconsistent conditional logic such as:
then the relation becomes cyclic. It says 1 < 2, 2 < 3, and 3 < 1. No sorting algorithm can turn that into a coherent ordered range.
Practical Rules for Safe Comparators
The safest way to write a comparator is to compare tuples of keys in order. In modern C++, that often looks like:
This approach is compact and much less error-prone than a long chain of ad hoc conditionals.
Another good rule is to test duplicate values, edge cases, and random inputs. Comparator bugs often stay hidden until the dataset becomes large enough to expose contradictions.
Common Pitfalls
The most common mistake is using <= or >= in the comparator. std::sort needs a strict relation, not a non-strict one.
Another mistake is returning different answers for the same pair over time, for example by reading mutable global state or random numbers inside the comparator.
People also assume "it sorted my test vector once" means the comparator is valid. Undefined behavior can look correct on one input and fail badly on another.
Finally, a comparator does not need to match operator< exactly. It only needs to provide a valid strict weak ordering.
Summary
- '
std::sortaccepts custom comparators, not justoperator<.' - The comparator must define a strict weak ordering.
- Violating that contract causes undefined behavior, which can include crashes.
- Using
<=is a classic invalid comparator bug. - Compare stable keys consistently and test edge cases to avoid subtle sorting failures.

