Шаблоны рекурсивных переменных
Я пытался использовать переменные шаблоны таким же образом, как я использую некоторые другие шаблоны, например: мы уже знаем, как вычислить число Фибоначчи или степень числа, используя метапрограммирование с объектами шаблона, оборачивающими статическое значение или значение перечисления.
Итак, первое, что я сделал, попытался специализировать переменную шаблона, и она работает как положено:
template <std::size_t VALUE> std::size_t value = VALUE;
template <> std::size_t value<666u> = 1u;
std::cout << value<0u> << '\n'; // "0" as expected
std::cout << value<1u> << '\n'; // "1" as expected
std::cout << value<2u> << '\n'; // "2" as expected
std::cout << value<666u> << '\n'; // "1" as expected!!
Зная, что специализация переменных шаблонов возможна, я попытался создать переменный шаблон Фибоначчи:
template <std::size_t ITERATION>
std::size_t fibonacci = fibonacci<ITERATION - 1u> + fibonacci<ITERATION - 2u>;
template <> std::size_t fibonacci<1u> = 1u;
template <> std::size_t fibonacci<0u> = 0u;
int main()
{
std::cout << fibonacci<5> << '\n'; // "8" expected;
return 0;
}
Ошибка, которую я получаю от Wandbox, заключается в следующем:
error: expected primary-expression before ';' token
template <std::size_t ITERATION> std::size_t fibonacci = fibonacci<ITERATION - 1u> + fibonacci<ITERATION - 2u>;
^
Я не знаю, что я делаю неправильно, и не понимаю ошибки. Я предполагаю, что ошибка может быть вызвана тем фактом, что шаблон переменной еще не определен, в то время как я уже использую его, поэтому я задаюсь вопросом, возможно ли вообще достичь моей цели с помощью шаблонов переменных.
Любой намек?
Большое спасибо.
1 ответ
Я предполагаю, что компиляторы еще не реализуют шаблоны переменных должным образом. Например, clang 3.7.0 компилирует ваш код, но (с небольшим исправлением ошибки: fibonacci<0u> = 1u
) выходы 0
вместо 8
за fibonacci<5>
,
Тем не менее, если мы делаем
std::cout << fibonacci<0> << '\n'; // "1" expected;
std::cout << fibonacci<1> << '\n'; // "1" expected;
std::cout << fibonacci<2> << '\n'; // "2" expected;
std::cout << fibonacci<3> << '\n'; // "3" expected;
std::cout << fibonacci<4> << '\n'; // "5" expected;
std::cout << fibonacci<5> << '\n'; // "8" expected;
тогда мы получим ожидаемые результаты. Weird!
Обновление Поскольку шаблоны функций более развиты, чем шаблоны переменных, это обходной путь:
template <std::size_t ITERATION>
constexpr std::size_t get_fibonacci()
{
return get_fibonacci<ITERATION - 1u>() + get_fibonacci<ITERATION - 2u>();
}
template <>
constexpr std::size_t get_fibonacci<0u>() {
return 1u;
}
template <>
constexpr std::size_t get_fibonacci<1u>() {
return 1u;
}
template <std::size_t ITERATION>
std::size_t fibonacci = get_fibonacci<ITERATION>();