std :: get <0> (...) и enum index - PullRequest
       62

std :: get <0> (...) и enum index

0 голосов
/ 30 января 2019

Чтобы сделать код более читабельным, я сделал следующее с помощью tuple:

std::tuple<uint32_t, uint32_t, uint32_t> key;

enum  tpl {
    arg1 = 0, arg2 = 1, arg3 = 2
};

Теперь я могу написать:

 auto _arg1 = std::get<tpl::arg1>(key);

Теперь у меня возникла проблема.Если я напишу:

auto arg1 = std::get<tpl::arg1>(key);

Переменная arg1 уже является перечислением.Поэтому я хочу переключиться на:

enum class tpl: int {
    arg1 = 0, arg2 = 1, arg3 = 2
};

Но здесь что-то не так.Компилятор говорит:

ошибка C2672: 'std :: get': не найдена соответствующая перегруженная функция

Какого типа этот индекс в std::get и может ли это бытьназван в определении класса enum?

Я пытался

const constexpr
const int 
....

Ответы [ 3 ]

0 голосов
/ 30 января 2019

Перечисление в области (enum class) не имеет неявного преобразования в целые числа любого рода.Поскольку std::get ожидает параметр шаблона целочисленного типа, такое преобразование должно произойти.

Но это невозможно, поэтому перегрузка не соответствует предоставленному аргументу шаблона.

Вы можете использовать "scoped"enum "hack one, к которому прибегали до C ++ 11:

struct tpl {
  enum : int {
    arg1 = 0, arg2 = 1, arg3 = 2
  };
};

Это делает идентификаторы области действия, но сохраняет неявные преобразования.Перечисления в C ++ 11 были введены, потому что обычно неявное преобразование не является желательной функцией, но в этом случае, я полагаю, это так.

0 голосов
/ 30 января 2019

Проблема в том, что перечисления с областью видимости неявным образом не преобразуются в их базовый тип.Вы можете сделать это вручную с помощью

std::get<static_cast<std::underlying_type_t<tpl>>(tpl::arg1)>(key);

, но поскольку ваша попытка повысить читабельность, это не может считаться хорошим решением.Вместо этого рассмотрите эту опцию:

namespace tpl {
   enum { arg1 = 0, arg2 = 1, arg3 = 2 };
}

std::get<tpl::arg1>(key);

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

В качестве дополнительного примечания, если вы обеспокоены последствиями для удобства чтения объектов std::tuple, вы можете вместо этого переключиться на тривиальный struct.

0 голосов
/ 30 января 2019
Параметр шаблона индекса

std::get имеет тип std::size_t.Перечисление с областью действия неявно преобразуется в его базовый тип.Поэтому, если вы настаиваете на его использовании, вы должны его разыграть.

auto arg1 = std::get<static_cast<int>(tpl::arg1)>(key);

Если вы хотите не упоминать базовый тип в приведении

auto arg1 = std::get<static_cast<std::underlying_type_t<tpl>>(tpl::arg1)>(key);
...