Почему это умножение кода шаблона вызывает переполнение?

#c

#c

Вопрос:

У меня здесь есть этот шаблон, который умножает числа следующим образом:

  • Если я передам 2 и 5 в качестве аргументов шаблона, он сгенерирует 5 чисел, умноженных на себя, начиная с 2 .
  • multiply_n_times<2, 5> должно быть равно pack<2, 4, 16, 256>

Это то, что я пробовал

 template<int Value, int Count, int... Is>
struct multiply_n_times : multiply_n_times<Value*Value, Count-1, Is..., Value> { };

template<int Value, int... Is>
struct multiply_n_times<Value, 0, Is...> : pack<Is...> { };
 

И когда я создаю его экземпляр, я получаю эту ошибку:

 main.cpp: In instantiation of 'struct multiply_n_times<65536, 1, 2, 4, 16, 256>':
main.cpp:15:8:   recursively required from 'struct multiply_n_times<4, 4, 2>'
main.cpp:15:8: required from 'struct multiply_n_times<2, 5>'

main.cpp:39:17:   required from here`  
main.cpp:15:8: error: overflow in constant expression [-fpermissive]
struct multiply_n_times : multiply_n_times<Value*Value, Count-1, Is..., Value> { };
 

Что я здесь сделал не так?

Ответ №1:

Последняя рекурсия, в которой отбрасывается первый аргумент, имеет переполнение.

Так что пропустите это:

 template<int Value, int... Is>
struct multiply_n_times<Value, 1, Is...> :
  pack<Is..., Value>
{ };
 

теперь мы никогда не вычисляем a Value*Value , который мы не будем использовать.

Оставьте 0 специализацию, если вам нужен 0 список квадратов длины.

Комментарии:

1. Спасибо. Знаете ли вы, где я могу стать лучше в ТМП?

Ответ №2:

При создании экземпляра Value умножается сам на себя в 5 раз
2 * 2 -> 4, 4 * 4 -> 16, 16 * 16 -> 256, 256 * 256 -> 65536 и 65536 * 65536 -> переполнение.
Если вы хотите остановиться на 4 — м шаге , то вам нужно либо использовать multiply_n_times<2, 4> , либо предоставить специализацию для Count = 1 , not Count = 0 .

Ответ №3:

@user2040251 имеет правильный ответ, ваше умножение вызывает переполнение ваших значений int. Чтобы быть немного более общим, вы можете ожидать, что для первоначального создания экземпляра с Value = v помощью and Count=n вы достигнете чисел до v ^ (2 ^ n) . Если вы измените свой код на stop at Count=1 , то вместо этого вы достигнете v ^(2 ^ (n-1)) .