xentara-utils v2.0.4
The Xentara Utility Library
Loading...
Searching...
No Matches
xentara::utils::tools::ThreeWayComparableWithExcept Concept Reference

Helper concept for implementing three-way comparison operators. More...

#include <xentara/utils/tools/Concepts.hpp>

Concept definition

template<typename Type, typename With, typename Except>
concept xentara::utils::tools::ThreeWayComparableWithExcept = detail::IsThreeWayComparableWithExcept<Type, With, Except>::value
Helper concept for implementing three-way comparison operators.
Definition Concepts.hpp:282

Detailed Description

Helper concept for implementing three-way comparison operators.

This concept can be used instead of std::three_way_comparable_with as a constraint for implementing three-way comparison member operators for a class. It behaves just like std::three_way_comparable_with, except that it excludes a single type.

This operator is used as a contraint for the parameter of a three-way comparison operator in the case where one would normally use std::three_way_comparable_with. Consider a class that has a name, and the class should be comparable with anything that can be compared with that name. We would like the implementation for this class to look like this:

class MyClass
{
public:
auto operator<=>(const MyClass &) const -> bool = default;
template <std::three_way_comparable_with<std::string> Lhs> // ERROR: constraint depends on itself
auto operator<=>(const Lhs &lhs) const -> bool
{
return _name <=> lhs;
}
private:
std::string _name;
};

Unfortunately, this will result in an error on most compilers when trying to compare two instances of MyClass, as the containt std::three_way_comparable_with on operator<=>(const Lhs &) with try to take into account possible instantiations of operator<=>(const Lhs &) itself, resulting in an infinite recursion. To avoid this, MyClass can be explicitly excluded by using ThreeWayComparableWithExcept instead of std::three_way_comparable_with:

class MyClass
{
public:
auto operator<=>(const MyClass &) const -> bool = default;
template <xentara::utils::tools::ThreeWayComparableWithExcept<std::string, MyClass> Lhs>
auto operator<=>(const Lhs &lhs) const -> bool
{
return _name <=> lhs;
}
private:
std::string _name;
};

Now, operator<=>(const Lhs &) can never be a cadidate for comparing two instances of MyClass, resolving the recursion.