Проверка того же перечисления, C

#c #struct #enums #integer #compare

#c #struct #перечисления #целое число #Сравнить

Вопрос:

Сейчас я абстрагируюсь от своей проблемы, но я нахожусь в такой ситуации. Допустим, у меня есть 2 перечисления, которые находятся в одном пространстве имен.

 namespace some_namespace {
    enum class Something{
        S,
        O,
        M,
        E,
        T,
        H,
        I,
        N,
        G
    };

    enum class Else{
        E,
        L,
        S
    };
}
 

Теперь давайте создадим 2 структуры, которые имеют в качестве статического поля некоторое значение этих перечислений.

 struct SomeStruct{
    static constexpr int enumValue = static_cast<int>(some_namespace::Something::T);
};

struct AnotherStruct {
    static constexpr int enumValue = static_cast<int>(some_namespace::Something::O);
};
 

Как я могу проверить, являются ли enumValues этих 2 структур одинаковыми enum class или нет? Я думаю, что я должен дать некоторые значения моим полям перечисления и использовать некоторый побитовый оператор для значений перечисления, чтобы различать? Может кто-нибудь помочь? спасибо)

Комментарии:

1. Вы не можете. C так не работает. К тому времени, когда вы закончите их объявлять, они будут просто простыми, безымянными int s. Их исходный тип перечисления был удален навсегда и потерян в мистике эфира.

2. Интересно, почему вы не сохраняете их как исходные перечисления?

3. Я думал, что есть способ присвоить элементам перечисления некоторые целые значения, а затем выполнить, например auto same.= SomeStruct::enumValue amp; AnotherStruct::enumValue if(same == 1){//same enum} else {//not same enum}

Ответ №1:

Используя только static_casted enumValue , невозможно отличить исходное перечисление (как указано @Sam). Вместо этого вы можете ввести новое поле, в котором хранится базовый тип класса enum, и использовать его для проведения различия.

 enum class E1{ One, Two };
enum class E2{Three, Four };

struct SomeStruct{
    static constexpr int enumValue = static_cast<int>(E1::One);
    using UnderlyingT = E1;
};

struct AnotherStruct {
    static constexpr int enumValue = static_cast<int>(E2::Three);
    using UnderlyingT = E2;
};

static_assert(!std::is_same_v<SomeStruct::UnderlyingT, AnotherStruct::UnderlyingT>);
 

Ссылка на код

Комментарии:

1. Фактически вы просто переопределяете перечисление таким образом, чтобы оно было структурой, что кажется бессмысленным.

Ответ №2:

Как уже указывалось в комментариях, вы не хотите преобразовывать свое перечисление в an int , если вы все еще хотите знать тип.

Могут быть некоторые причины для сохранения типа и области видимости при желании неявного преобразования в базовый тип.

Что вы могли бы сделать, так это обернуть перечисление в класс, который преобразует как базовый тип, так И фактическое перечисление.

 #include <type_traits>
template<typename TEnum>
class ImplicitEnumConverter final
{
public:
    TEnum e;
    using TUnderlyingType = std::underlying_type_t<TEnum>;

    constexpr ImplicitEnumConverter(TEnum e) : e{e} {}

    constexpr operator TUnderlyingType() const noexcept
    {
        return static_cast<TUnderlyingType>(e);
    }
    constexpr operator TEnum() const noexcept
    {
        return e;
    }
};

struct SomeStruct{
    static constexpr auto enumValue = ImplicitEnumConverter{some_namespace::Something::T};
};
 

Код в компиляторе-проводнике

Таким образом, вы можете сохранить всю типобезопасную информацию там, где это имеет значение, И вы можете неявно преобразовать ее в int .

Ответ №3:

Ответ был проще, чем я думал.

Поэтому я объявляю перечисление следующим образом.

 namespace some_namespace {
    enum class Something{
        S = 0,
        O = 2,
        M = 4,
        E = 6,
        T = 8,
        H = 10,
        I = 12,
        N = 14,
        G = 16
    };

    enum class Else{
        E = 1,
        L = 3,
        S = 5
    };
}
 

И затем это заставляет меня проверить, имеют ли два целых значения одинаковую четность или нет. Таким образом

 if((SomeStruct::enum_value   AnotherStruct::enum_value) % 2 == 0) {
    // Same enum
} else {
    // not same enum.
}