Преобразовать скучный список операторов switch во что-то более короткое и приятное на вид?

#c #c 11

#c #c 11

Вопрос:

У меня есть оператор switch, который выполняется следующим образом

 switch (abc) {
  case FILE_0:
       lf = m_a->olf[0];
       kf = m_a->pkf[0];
       break;
  case FILE_1:
       lf = m_a->olf[1];
       kf = m_a->pkf[1];
       break;
  .
  .
  default:
       LOG_ERR << "Wrong type to check";
       return 0;
}
  

Это происходит около 30 раз, и в итоге у меня получается 30 случаев в этом одном коммутаторе.
Есть ли способ сократить его в C 11? Например. с помощью шаблонов.

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

1. Как именно определяются FILE_0 , FILE_1 , и т.д.?

2. Не забывайте break; , если вы остаетесь с. switch()

3. Кроме того, ваши дела проваливаются. Это намеренно?

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

5. Я делаю здесь попытку, но является FILE_0 ли использование элемента 0 ( lf = m_a->olf[0]; ) и FILE_1 использование элемента 1 ( lf = m_a->olf[0]; ) шаблоном? Является ли значение FILE_0 фактически 0, а FILE_1 фактически 1? Если да (или вы могли бы сделать это так lf=m_a->olf[abc] , это ответ. Здесь недостаточно кода, чтобы действительно понять, что вы делаете.

Ответ №1:

Ваш код не настолько велик, чтобы быть уверенным в намерении, хотя, из того, что я вижу во фрагменте, вы действительно хотите преобразовать символическое значение в индекс. (Могу ли я предположить, что это перечисление?)

Что бы я сделал, так это переместил этот код в отдельную функцию:

 auto fileEnumToIndex(FileEnum file) {
    switch (file) {
       case FILE_0: return 0;
       case FILE_1: return 1;
       default: __builtin_unreachable();
    }
}
  

Ваш код, чем изменения в:

  auto index = fileEnumToIndex(abc);
   lf = m_a->olf[index];
   kf = m_a->pkf[index];
  

Если FileEnum является реальным перечислением, вы можете изменить код в функции fileEnumToIndex на простой static_cast

Чтобы охватить регистр по умолчанию, вы могли бы вернуть a std::optional и использовать std::nullopt case для некоторой обработки ошибок. Однако, когда FileEnum является фактическим перечислением, я бы предположил обработку ошибок при определении этого значения.

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

1. Спасибо JVApen. да, FILE_0, FILE_1 — это реальное перечисление. Я просто хочу избежать повторения случаев внутри коммутатора 29 раз, поскольку там есть шаблон. Но я не понимаю, что вы имеете в виду в последнем предложении — «Если FileEnum является реальным перечислением, вы можете изменить код в функции fileEnumToIndex на простой static_cast»

2. return static_cast<int>(file); поскольку числовые значения перечисления изменяются от 0 до N, если вы их не переопределяете

Ответ №2:

Вы можете создать карту abc и индекс и использовать ее для определения индекса.

 // somewhere, maybe outside functions
static const std::unordered_map<abc_type, int> table = {
    {FILE_0, 0},
    {FILE_1, 1},
    ...
};

// inside function
auto idx_itr = table.find(abc);
if (idx_itr != table.end()) {
   lf = m_a->olf[*idx_itr];
   kf = m_a->pkf[*idx_itr];
} else {
    // default case
}
  

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

1. это делает что-то совершенно другое

2. @P__JsupportswomeninPoland Да, если провал является преднамеренным.