Подтвердить что ты не робот

Шаблоны метапрограммирования - разница между использованием Enum Hack и статическим контуром

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

EX: (Фибоначчи через TMP)

template< int n > struct TMPFib {
  static const int val =
    TMPFib< n-1 >::val + TMPFib< n-2 >::val;
};

template<> struct TMPFib< 1 > {
  static const int val = 1;
};

template<> struct TMPFib< 0 > {
  static const int val = 0;
};

против.

template< int n > struct TMPFib {
  enum {
    val = TMPFib< n-1 >::val + TMPFib< n-2 >::val
  };
};

template<> struct TMPFib< 1 > {
  enum { val = 1 };
};

template<> struct TMPFib< 0 > {
  enum { val = 0 };
};

Зачем использовать один над другим? Я читал, что enum hack использовался до того, как static const поддерживался внутри классов, но зачем использовать его сейчас?

4b9b3361

Ответ 1

Перечисления - это не lvals, статические значения-члены и, если они переданы по ссылке, шаблон будет instanciated:

void f(const int&);
f(TMPFib<1>::value);

Если вы хотите делать чистые вычисления времени компиляции и т.д., это нежелательный побочный эффект.

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

В приведены более подробные рекомендации по кодированию и более старая нить в архивах повышения в отношении предмета.

Ответ 2

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

Последнее лучше поддерживается некоторыми более старыми компиляторами.

Ответ 3

На обратной стороне ответа @Georg, когда структура, содержащая статическую константную переменную, определяется в специализированном шаблоне, ее необходимо объявить в источнике, поэтому компоновщик может найти его и фактически дать ему адрес, на который можно ссылаться. Это может быть неоправданно (в зависимости от желаемых эффектов) вызывать неэлементный код, особенно если вы пытаетесь создать только библиотеку с заголовком. Вы можете решить эту проблему путем преобразования значений в функции, возвращающие значение, которое также может открыть шаблоны для информации о времени выполнения.