How is non-deprecated different enum type comparison supposed to be conducted?

137 views Asked by At

I have this piece of template code somewhere within a template class with template types S,T:

using answer_type = Flag<( (std::is_same_v<S,T>) and (s==t) )>;

Clang says:

warning: comparison of different enumeration types is deprecated.

So GPT proposes I create one metric ton of boilerplate to prevent the comparison:

template <typename S, typename T, S s, T t>
struct is_same_and_equal {
    static constexpr bool value = false;
};

template <typename T, T s, T t>
struct is_same_and_equal<T, T, s, t> {
    static constexpr bool value = s == t;
};

so that

using answer_type = Flag< is_same_and_equal<S, T, s, t>::value >;

Now, since this is marked as deprecated, is there an equally short-as-original solution that is non-deprecated? Why exactly is the original solution disadvantageous? (Is it even?)

Remark

The application is: "If T enum type Color and S is enum type Material" then return false. If both types are Color or material then compare their markedness.

2

There are 2 answers

0
Ted Lyngmo On BEST ANSWER

You could use constexpr-if to avoid the comparison in case S and T are not the same type:

template<class S, class T, S s, T t>
auto foo() {
    using answer_type = Flag<[]{if constexpr (std::is_same_v<S,T>) return s == t;
                                else return false;}()>;
}
2
463035818_is_not_an_ai On

Not sure if this meets your case:

#include <type_traits>

enum S {};
enum T {};

template <bool> struct Flag {};

template <S s, T t>
struct foo {
    using answer_type = Flag<( (std::is_same_v<S,T>) and (s==t) )>;
};

If it does, you can cast either of the two to the other type. You already know that they are of same type:

using answer_type = Flag<( (std::is_same_v<S,T>) and (s==static_cast<S>(t)) )>;

Its a bit of a hack to silence the warning, because and is short cuirciting and s and t are constant expressions, hence no enums of different type are compared. The compiler isnt trying to be too clever to realize what std::is_same actually does, its a trait like others, hence its not obvious that it returns false when S and T are different types.