std::equality_comparable_with, std::totally_ordered_with, and strongly-typed integers

Viewed 114

I'm defining a strongly-typed integer type while playing around with C++20 concepts, like below.

class strong_int {
public:
    using integral_type = int;

    explicit strong_int( integral_type ) noexcept;

    explicit operator integral_type() const noexcept;

    constexpr auto operator<=>( const strong_int& ) const noexcept;

private:
    integral_type m_value;
};

constexpr auto operator<=>( const strong_int&, const int& ) noexcept;
constexpr auto operator<=>( const int&, const strong_int& ) noexcept;

However, I cannot use strong_int and int together in APIs expecting their parameters to be std::totally_ordered_with each other, because std::totally_ordered_with<T,U> expects that std::common_reference_t<T,U> exists. This does not hold for strong_int and int since the conversions between them are explicit. For example, the following fails:

template<typename T1, typename T2>
    requires std::totally_ordered_with<T1,T2>
void fn0( const T1&, const T2& );

void fn1() {
    strong_int si{0};
    int        i;

    fn0( si, i ); // compile error here
}

Is there a way to keep both the following?

  • conversions between strong_int and int are explicit

  • use strong_int si and int i in contexts that want si and i to satisfy std::totally_ordered_with

0 Answers
Related