#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.
}