CodexBloom - Programming Q&A Platform

std::optional not behaving as expected when used with a custom comparison operator in C++20

πŸ‘€ Views: 58 πŸ’¬ Answers: 1 πŸ“… Created: 2025-06-14
c++ std-optional sorting custom-operator C++

I'm testing a new approach and I'm working on a project and hit a roadblock. I'm sure I'm missing something obvious here, but I've searched everywhere and can't find a clear answer. I am facing an issue with `std::optional` in C++20 when trying to use it with a custom comparison operator. I have a class `Item` that contains an `std::optional<int>` member for an optional value. I implemented a custom comparison operator to sort a vector of `Item` instances based on the optional value. However, I am getting unexpected results when sorting the vector, especially when some `Item` instances have no value (i.e., `std::nullopt`). Here’s the relevant part of my code: ```cpp #include <iostream> #include <vector> #include <algorithm> #include <optional> class Item { public: std::optional<int> value; Item(std::optional<int> v) : value(v) {} bool operator<(const Item& other) const { // Custom comparison: items with a value are less than those without if (value && other.value) { return *value < *other.value; } return !value; // my intention: items without a value should be considered greater } }; int main() { std::vector<Item> items = {Item(3), Item(std::nullopt), Item(1), Item(2), Item(std::nullopt)}; std::sort(items.begin(), items.end()); for (const auto& item : items) { if (item.value) { std::cout << *item.value << " "; } else { std::cout << "nullopt "; } } return 0; } ``` When I run the above code, I expect the output to be `1 2 3 nullopt nullopt`, but instead, I am getting `1 2 3 nullopt nullopt`, which seems correct, but I observe that the `nullopt` instances are getting sorted as if they were having a value of `0`. I’d like to ensure that items without values are indeed treated as greater than those with values during the sorting. I’ve tried different approaches, including tweaking the comparison logic, but nothing seems to yield the desired result. Is there something I'm missing about how `std::optional` interacts with comparison operators that could lead to this unexpected behavior? Any insights on best practices for sorting `std::optional` values would be greatly appreciated. I'm working on a service that needs to handle this. Any ideas what could be causing this? This issue appeared after updating to C++ 3.11. Any suggestions would be helpful.