Шаблоны метапрограммирования - разница между использованием 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 поддерживался внутри классов, но зачем использовать его сейчас?
Ответы
Ответ 1
Перечисления - это не lvals, статические значения-члены и, если они переданы по ссылке, шаблон будет instanciated:
void f(const int&);
f(TMPFib<1>::value);
Если вы хотите делать чистые вычисления времени компиляции и т.д., это нежелательный побочный эффект.
Основное историческое различие заключается в том, что перечисления также работают для компиляторов, где инициализация значений класса в классе не поддерживается, это должно быть исправлено в большинстве компиляторов сейчас.
Также могут быть различия в скорости компиляции между enum и static consts.
В приведены более подробные рекомендации по кодированию и более старая нить в архивах повышения в отношении предмета.
Ответ 2
Для некоторых первый может казаться менее взломанным и более естественным. Также у него есть память, выделенная для себя, если вы используете класс, так что вы можете, например, взять адрес val.
Последнее лучше поддерживается некоторыми более старыми компиляторами.
Ответ 3
На обратной стороне ответа @Georg, когда структура, содержащая статическую константную переменную, определяется в специализированном шаблоне, ее необходимо объявить в источнике, поэтому компоновщик может найти его и фактически дать ему адрес, на который можно ссылаться. Это может быть неоправданно (в зависимости от желаемых эффектов) вызывать неэлементный код, особенно если вы пытаетесь создать только библиотеку с заголовком. Вы можете решить эту проблему путем преобразования значений в функции, возвращающие значение, которое также может открыть шаблоны для информации о времени выполнения.