Генерация целого числа времени компиляции из литеральной строки

У меня проблема с непереносимым кодом, который работает так, как задумано на компиляторе ARM RealView, но VC ++, GCC отказываются его компилировать, а QAC ++ (инструмент статического анализа) выдает предупреждение.

Эта проблема

У меня есть система, которая должна анализировать мнемонические идентификаторы в сообщениях. Мнемоника — это все трехсимвольные 8-битные строки ASCII. Чтобы упростить и оптимизировать синтаксический анализ, а не выполнять сравнение строк с мнемонической строкой, я упаковываю строку в 32-разрядное целое число и выполняю целочисленное сравнение.

Далее, чтобы иметь возможность использовать переключатель / регистр, а не цепочку if-elseif, у меня есть макрос, который принимает буквенную строку и генерирует соответствующее целое число, которое в ARM RealView является постоянной времени компиляции, но не в GCC x86 / Linux или VC ++ / Windows:

// Note:  Do not change C cast to static_cast because compiler complains when used in switch/case
#define CONST_MNEMONIC( mn ) ((uint32_t)(((#mn)[2]<<16)|((#mn)[1]<<8)|((#mn)[0])))

Затем он используется в целевом коде ARM следующим образом:

switch( packed_mnemonic )
{
case CONST_MNEMONIC(RST) :
...
break ;

case CONST_MNEMONIC(SSD) :
...
break ;

case CONST_MNEMONIC(DEL) :
...
break ;

default:
...
break ;
}

Конечно, метка case должна быть константой времени компиляции, но, очевидно, это не так для всех компиляторов. Код является непереносимым, и я предполагаю, что он не определен, или поведение, определяемое реализацией, или просто неправильно!

Вопросы

Очевидные портативные решения имеют недостатки эффективности и ремонтопригодности, поэтому у меня есть два вопроса:

  1. Почему этот код не переносим — что делает макрос не постоянным во время компиляции в некоторых компиляторах?

  2. Есть ли переносимое решение для генерации желаемой постоянной времени компиляции из мнемонической строки?

6

Решение

С C ++ 11 вы можете использовать constexpr функция:

constexpr int CONST_MNEMONIC(const char* s)
{
return (static_cast<int>(s[2]) << 16) +
(static_cast<int>(s[1]) <<  8) +
static_cast<int>(s[0]);
}
5

Другие решения

Здесь он прекрасно компилируется с gcc 4.8 и clang 3.4 …

В C ++ 11 вы можете использовать:

constexpr uint32_t CONST_MNEMONIC(const char (&s)[4])
{
return (uint32_t(s[2]) << 16) | (uint32_t(s[1]) << 8) | uint32_t(s[0]);
}
3

По вопросам рекламы [email protected]