C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Manifold comparison operator

From: Fabio Alemagna <falemagn_at_[hidden]>
Date: Sun, 24 Sep 2023 16:05:38 +0200
Il giorno gio 7 set 2023 alle ore 23:56 Ben Crowhurst via
Std-Proposals <std-proposals_at_[hidden]> ha scritto:
>
> We propose a new range of conditional operators for C++:
>
> * [^] one-of
> * [&] all-of
> * [|] any-of
> * [!] none-of

[...]

For my own needs I came up with a "any_of" using template
metaprogramming, which allows one to write something like:
    if (x == any_of(a, b, c)) { /*...*/ }

Where a, b and c are instances of potentially heterogeneous types.

Right now only operator== is implemented, that's what I needed, but
it's trivial to implement all the others, and following the same
pattern it's easy to see how to implement one_of, all_off, none_of as
well.

Here's the code (I am sure you guys will find many ways to improve upon it):

    #include <type_traits>
    #include <tuple>

    template <typename T, typename U, typename = void>
    struct equality_comparable: std::false_type{};

    template <typename T, typename U>
    struct equality_comparable<T, U, std::void_t<
        decltype(std::declval<T>() == std::declval<U>(),
std::declval<U>() == std::declval<T>())>
> : std::true_type{};

    template <typename... Ts>
    struct any_of: std::tuple<Ts...> {
        using std::tuple<Ts...>::tuple;

        template <typename T>
        constexpr bool operator ==(const T &rhs) const {
            return impl(rhs, std::make_index_sequence<sizeof...(Ts)>());
        }

        private:
        template <typename T, std::size_t... Is>
        constexpr bool impl(const T &v, const std::index_sequence<Is...>&) const
        {
            auto check = [&v](const auto &e) {
                using E = std::decay_t<decltype(e)>;

                if constexpr (equality_comparable<T, E>::value) {
                    return v == e;
                }
                else {
                    return false;
                }
            };

            return (check(std::get<Is>(*this)) || ...);
        }
    };

    template <typename... Ts>
    any_of(Ts &&... ts) -> any_of<Ts...>;

    template <typename T, typename... Us>
    constexpr bool operator==(T &&lhs, const any_of<Us...> &rhs)
    {
        return rhs == lhs;
    }

It seems to be working fine, but comments and corrections are greatly welcome.

I'd love to see something like this standardized, however the names in
std:: are already taken. What do you guys say?

Fabio

Received on 2023-09-24 14:05:51