Если вам нужно выполнить поиск во время выполнения, следующий метод будет работать со сложностью O (1) в обоих направлениях.
Поскольку все ваши перечислители A
и B
не инициализированы, первый перечислитель имеет значение ноль, второй имеет значение 1
и т. Д.
Рассматривая эти начальные с нуля целые числа как индексы массивов, мы можем построить двунаправленную карту, используя два массива.
Например, принимая текущее отображение как
A::FirstA (=0) <--> B::SecondB (=1),
A::SecondA (=1) <--> B::FirstB (=0),
, тогда давайте определим следующие два массива
A arrA[2] = {A::SecondA, A::FirstA},
B arrB[2] = {B::SecondB, B::FirstB},
, где arrA[i]
- это перечислитель A
, соответствующий i
-ому перечислителю B
, и наоборот.
В этой настройке мы можем выполнить поиск от A a
до B
как arrB[std::size(a)]
и наоборот со сложностью O (1).
Следующий класс biENumMap
является примером реализации вышеуказанного двунаправленного метода с C ++ 14 и более поздними версиями.
Обратите внимание, что поскольку расширенный * constexpr доступен из C ++ 14, здесь ctor также может быть константным выражением.
Две перегрузки operator()
являются функциями поиска из A
и B
соответственно.
Это также могут быть константные выражения, и этот класс позволяет нам выполнять двунаправленный поиск как во время компиляции, так и во время выполнения:
template<std::size_t N>
class biENumMap
{
A arrA[N];
B arrB[N];
public:
constexpr biENumMap(const std::array<std::pair<A,B>, N>& init)
: arrA(), arrB()
{
for(std::size_t i = 0; i < N; ++i)
{
const auto& p = init[i];
arrA[static_cast<std::size_t>(p.second)] = p.first;
arrB[static_cast<std::size_t>(p.first) ] = p.second;
}
}
constexpr A operator()(B b) const{
return arrA[static_cast<std::size_t>(b)];
}
constexpr B operator()(A a) const{
return arrB[static_cast<std::size_t>(a)];
}
};
Мы можем использовать этот класс следующим образом:
DEMO
// compile-time construction.
constexpr biEnumMap<3> mapper({{
{A::FirstA , B::SecondB },
{A::SecondA , B::FirstB },
{A::InvalidA, B::InvalidB} }});
// compile-time tests, A to B.
static_assert(mapper(A::FirstA ) == B::SecondB );
static_assert(mapper(A::SecondA ) == B::FirstB );
static_assert(mapper(A::InvalidA) == B::InvalidB);
// compile-time tests, B to A.
static_assert(mapper(B::FirstB ) == A::SecondA );
static_assert(mapper(B::SecondB ) == A::FirstA );
static_assert(mapper(B::InvalidB) == A::InvalidA);
// run-time tests, A to B.
std::vector<A> vA = {A::FirstA, A::SecondA, A::InvalidA};
assert(mapper(vA[0]) == B::SecondB );
assert(mapper(vA[1]) == B::FirstB );
assert(mapper(vA[2]) == B::InvalidB);
// run-time tests, B to A.
std::vector<B> vB = {B::FirstB, B::SecondB, B::InvalidB};
assert(mapper(vB[0]) == A::SecondA );
assert(mapper(vB[1]) == A::FirstA );
assert(mapper(vB[2]) == A::InvalidA);