параметры шаблона, #define и дублирование кода - PullRequest
7 голосов
/ 01 сентября 2010

У меня много такого кода:

#define WITH_FEATURE_X

struct A {
#ifdef WITH_FEATURE_X
  // ... declare some variables Y
#endif
  void f ();
};

void A::f () {
  // ... do something
#ifdef WITH_FEATURE_X
  // ... do something and use Y
#else
  // ... do something else
#endif
  // ... do something
}

и я хотел бы заменить #defines параметрами шаблона:

template < int WITH_FEATURE_X > // can be 0 or 1
struct A;

Но я не хочу дублировать почти весь код A :: f () для A <0> :: f () и A <1> :: f () только для нескольких строк, которые зависят параметр. Я также не хочу вызывать функции вместо предыдущих #ifdefs. Какое общее решение?

Ответы [ 4 ]

2 голосов
/ 01 сентября 2010

Если вы хотите избежать дублирования логики функции f, вы можете использовать шаблон метода шаблона (нет, это не template.

template <bool enabled>
class helper {
protected:
    void foo() { /* do nothing */ }
};

template <>
class helper<true> {
protected:
    Y y;
    void foo() { /* do something with y */ }
};

struct A : private helper<WITH_FEATURE_X> {
    void f() {
        // common stuff

        foo(); // optimized away when WITH_FEATURE_X is false

        // more common stuff
    }
};
1 голос
/ 01 сентября 2010

Я считаю, что то, что вы хотите, является эквивалентом команды "static if", которая существует на языке D. Я боюсь, что такая функция не существует в C ++.

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

EDIT
Если ваши операторы #ifdef используются для выполнения одной и той же подзадачи по-разному, то определение подфункций является правильным решением. Это сделает ваш код более читабельным, а не менее.

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

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

EDIT2
Я забыл упомянуть ответ на первую часть вашего кода: используйте следующий трюк для добавления или удаления членов в зависимости от «функции».

namespace helper
{
  template<int feature>
  struct A;

  template<>
  struct A<0> { // add member variables for case 0 };

  template<>
  struct A<1> { // add member variables for case 1 };
}

template<int feature>
class A : private helper::A<feature>
{
  // ... functions here
};
0 голосов
/ 01 сентября 2010

Я не понимаю смысла обычного дублирования кода. Если вы используете параметр шаблона, вы просто заменяете ваш #ifdef на if (WITH_FEATURE_X). Вы говорите о раздувании кода компилятором? Поскольку вы пытаетесь заменить #ifdef, я предполагаю, что вы будете использовать A <0> или A <1> в любой точке. Таким образом, я не вижу раздувания кода даже компилятором.

0 голосов
/ 01 сентября 2010

Обычное решение, я просто боюсь использовать #ifdef.: -)

...