Захотел результат <=> запихнуть в switch и сделал враппер
От: Sm0ke Россия ksi
Дата: 28.01.22 08:04
Оценка: 68 (1)
Вот они сделали, что std::strong_ordering::equal и прочие нельзя было запихнуть в switch case.
Но это не проблема, пишем враппер!

#include <compare>

enum class compare_strict {
    unordered = -2,

    less = -1,
    greater = +1,

    equal_strong = 0,
    equal_weak = 2,
    equal_partial = 3
};

template <typename Result>
constexpr Result cast_ordering(std::strong_ordering from) {
    using t_from = decltype(from);
    return from == t_from::less ? Result::less : (
        from == t_from::greater ? Result::greater : Result::equal_strong
    );
}

template <typename Result>
constexpr Result cast_ordering(std::weak_ordering from) {
    using t_from = decltype(from);
    return from == t_from::less ? Result::less : (
        from == t_from::greater ? Result::greater : Result::equal_weak
    );
}

template <typename Result>
constexpr Result cast_ordering(std::partial_ordering from) {
    using t_from = decltype(from);
    return from == t_from::less ? Result::less : (
        from == t_from::greater ? Result::greater : (
            from == t_from::unordered ? Result::unordered : Result::equal_partial
        )
    );
}


Теперь можно просто вот так:
int main() {
    switch( cast_ordering<compare_strict>(0.0/0.0 <=> 1.1) ) {
        case compare_strict::less :
        std::cout << "less\n"; break;

        case compare_strict::greater :
        std::cout << "greater\n"; break;

        case compare_strict::equal_partial :
        std::cout << "equal_partial\n"; break;

        case compare_strict::equal_weak :
        std::cout << "equal_weak\n"; break;

        case compare_strict::unordered :
        std::cout << "unordered\n"; break;

        default:
        std::cout << "equal_strong\n";
    }
    return 0;
}


Но если вы не хотите различать equal_partial, equal_weak, equal_strong — для этого пишем ещё один enum, чтобы подставить его как Result в cast_ordering<>() :
enum class compare_simple {
    less = -1,
    equal_any = 0,
    greater = +1,

    equal_strong = equal_any,
    equal_weak = equal_any,
    equal_partial = equal_any,

    unordered = less
};

int main() {
    // Вы могли заметить, что в compare_simple ещё и unordered работает как less !
    switch( cast_ordering<compare_simple>(0.0/0.0 <=> 1.1) ) {
        case compare_simple::less :
        std::cout << "less\n"; break;

        case compare_simple::greater :
        std::cout << "greater\n"; break;

        case compare_simple::equal_any :
        std::cout << "equal\n"; break;

        default:
        std::cout << "произошла фигня!\n";
    }
    return 0;
}


Короче таким макаром можно делать свои кастомные енумы результатов сравнения со своими значениями underlying тайпа.
Одно меня смущает однако что функция cast_ordering<>() кушает накладные расходы на трансформацию, но я думаю это не всегда критично.
Отредактировано 13.08.2023 19:01 Sm0ke . Предыдущая версия .
cast cpp comparison switch
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.