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_intandintareexplicituse
strong_int siandint iin contexts that wantsiandito satisfystd::totally_ordered_with