Удалить / вставить код во время компиляции без дублирования в C ++ - PullRequest
3 голосов
/ 02 октября 2011

У меня есть шаблон класса, который принимает несколько типов. Один тип есть только для определения политики. Этот класс определяет, как функция может работать в определенных случаях.

Допустим, это одна из функций:

/* this code is part of a class */

    template <typename T, typename T_Policy> // Not important but just showing the template parameters of the class

    void Allocate(unsigned int numElements)
    {
      // Some code here
      while (someCondition) // Other functions don't have the loop, this is just an example
      {
        // Some code here

        if (T_Policy::trackElements) { /* some code here */ }
        if (T_Policy::verbose) { /* some code here */ }
        if (T_Policy::customManager) { /* some code here */ }
        /* and a few other policies */
      }
      // Some more code here
    }

Мне бы хотелось, чтобы строки кода, использующие политики, компилировались, а не полагались на операторы if. Один очевидный способ - поместить цикл while в перегруженные функции, каждая из которых принимает фиктивный объект с определенным типом политики. Но это означает много дублирования кода. Подобные подходы со специализацией шаблона также приведут к дублированию кода.

Есть ли способ компилировать код без дублирования кода?

Ответы [ 3 ]

3 голосов
/ 02 октября 2011

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

1 голос
/ 02 октября 2011

Вы всегда можете изменить код

   if (T_Policy::trackElements) { /* some code here */ }

в

template <bool b>
void trackElementPhase() {
  /* some code here */
}

template <>
void trackElementPhase<false>() {} // empty body

 ... later in the code

     trackElementPhase<T_Policy::track_elements>();

Конечно, T_Policy::track_elements должна быть постоянной времени компиляции для этого.

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

   if (T_Policy::trackElements) { /* some code here */ }

если условие является постоянной времени компиляции.

0 голосов
/ 02 октября 2011

Вы можете использовать рекурсивные шаблоны для составления списка политик, к которым все применяются, например:

#include <iostream>
template <typename Policy, typename Next=void>
struct policy_list {
  static void apply() {
    Policy::implement();
    Next::apply();
  }
};

template <typename Policy>
struct policy_list<Policy, void> {
  static void apply() {
    Policy::implement();
  }
};

struct first_policy {
  static void implement() { std::cout << "Policy 1" << std::endl;  }
};

struct second_policy {
  static void implement() { std::cout << "Policy 2" << std::endl; }
};

int main() {
  typedef policy_list<first_policy, policy_list<second_policy> > policy;
  while (1) {
    policy::apply();
  }
}

Для трех политик вам необходимо изменить typedef на:

typedef policy_list<first_policy, policy_list<second_policy, policy_list<third_policy> > > policy;

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

Если у вас есть C ++ 11, вы можете несколько упростить policy_list, используя шаблоны с переменными числами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...