Использование шаблонов C ++ или макросов для генерации функции времени компиляции - PullRequest
1 голос
/ 14 июля 2010

У меня есть код, который работает во встроенной системе, и он должен работать очень быстро.Я знаю C и макросы, и этот конкретный проект в основном написан на C, но он также использует шаблоны C ++ [все больше и больше].Существует встроенная функция:

inline my_t read_memory(uint32 addr) {
  #if (CURRENT_STATE & OPTIMIZE_BITMAP)
    return readOptimized(addr);
  #else
    return MEMORY[addr];
  #endif
}

Эта функция считывает данные из памяти оптимизированным или традиционным способом на основе текущего состояния и растрового изображения, которое указывает, следует ли использовать оптимизацию в определенном состоянии.

#define STATE_A 0x0001
#define STATE_B 0x0010
#define STATE_C 0x0100
#define STATE_D 0x1000

#define OPTIMIZE_BITMAP 0x1010 // optimize states d and b

и в процессе выполнения (хорошо, компиляция) я попытался переопределить CURRENT_STATE следующим образом:

int main(){
  #define CURRENT_STATE STATE_A
  do_a();
  #undef CURRENT_STATE
  #define CURRENT_STATE STATE_B
  do_b();
  ....
}

Все функции do_X () делают вызовы read_memory ().Я не мог заставить этот подход работать.Значение текущего состояния всегда STATE_A, как я вижу, когда использую операторы #warning.Это не мой вопрос, хотя, если вы поможете мне с этим, я буду счастлив вдвойне.Итак, мой вопрос: есть ли способ сделать это, используя шаблоны вместо макросов?

Еще немного информации: мне нужно использовать встроенную функцию, потому что я не могу экспортировать MEMORY [], и этобиблиотечная функция.Я действительно предпочитаю не изменять прототип функции (например, read_memory () ...), но это подойдет.Кроме того, простите мою безвестность.

большое спасибо,

Ответы [ 2 ]

10 голосов
/ 14 июля 2010

Встроенная функция будет проанализирована один раз в точке в единице перевода, где она объявлена, и будет использовано состояние макросов в этой точке. Многократный вызов функции с разными макросами не изменит определение функции.

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

template<unsigned state>
inline my_t read_memory(uint32 addr) {
  if(state & OPTIMIZE_BITMAP)
    return readOptimized(addr);
  else
    return MEMORY[addr];
}

int main(){
    read_memory<STATE_A>(some_addr);
    read_memory<STATE_B>(some_addr);
    ....
}

Компилятор поймет, что state & OPTIMIZE_BITMAP является константой, и оптимизирует ту или иную ветвь if для каждого экземпляра шаблона.

5 голосов
/ 14 июля 2010

Я думаю, что вы, возможно, неправильно понимаете, что компилятор (или, скорее, препроцессор) делает с # define.

Ваш пример (приведенный ниже) бесполезен, поскольку CURRENT_STATE не используется между #define и#undef.Препроцессор не «выполняет» ваш код и не расширяет встроенную функцию do_a ().#defines и раскрытие макросов могут происходить ТОЛЬКО В ПОРЯДКЕ СТРОК В ВАШЕМ ИСТОЧНИКЕ.

  #define CURRENT_STATE STATE_A
  do_a();
  #undef CURRENT_STATE

Вот решение на основе препроцессора, если шаблоны наполняют вас ужасом.Давайте предположим, что do_a() должен использовать оптимизированную версию.

inline my_t read_memory(uint32 addr) 
{
  return MEMORY[addr];
}

inline my_t read_memory_optimized(uint32 addr) 
{
  return readOptimized(addr);
}

Теперь создайте DO_CONFIG.H

#if defined(DO_A) || (defined(DO_C) || ...)
  #define READ_MEMORY read_memory_optimized
#else
  #define READ_MEMORY read_memory

В DO_A.C, добавьте это вверху

#define DO_A
#include DO_CONFIG.H

... и использовать x=READ_MEMORY(addr) вместо x=read_memory(addr).Чтобы переключиться с оптимизированного на неоптимизированный, просто измените DO_CONFIG.H

...