Я пишу очень простой шаблонный класс, использующий метапрограммирование для вычисления суммы во время компиляции, как показано ниже:
#include <iostream>
using namespace std;
template<int N>
class Sum
{
public:
enum {value = N + Sum<N-1>::value };
};
template<>
class Sum<0>
{
public:
enum {value = 0};
};int main()
{
cout << Sum<501>::value << endl;
}
Интересная вещь:
Когда дело доходит до суммы<501>, компиляция не удалась с:
sum.cpp: 9: создается из
Sum<500>' sum.cpp:9: instantiated
сумма<501> ‘sum.cpp: 22: создан здесь
fromsum.cpp: 9: ошибка: неполный тип
Sum<1>' used in nested name
значение ‘не целое число
specifier sum.cpp:9: error: enumerator value for
постоянная
сумма<501> сообщит об ошибке суммы<1>, сумма<502> сообщит об ошибке суммы<2>, разница всегда 2, мне кажется, у компилятора есть лимит ресурсов 500.
Есть идеи по этому поводу? и есть ли способ преодолеть эти ограничения?
Благодарю.
Редактировать:
Спасибо, ребята, дело не в алгоритме, а в ограничении компилятора — я знаю, что есть простой способ получить сумму 🙂
Edit2:
sum.cpp: 9: 14: ошибка: глубина создания шаблона превышает максимум
1024 (используйте -ftemplate-глубина = чтобы увеличить максимум)
Sum Сумма класса<1> ’sum.cpp: 9: 14: рекурсивно создается из
«Sum<1024> ’sum.cpp: 9: 14: создается из‘ Sum<1025>»
sum.cpp: 22: 22: создается отсюда
так что да, используйте ftemplate-глубина — правильный путь. Но как насчет окон? верхний предел для VC9.0 равен 499, и, похоже, нет возможности установить глубину шаблона, см. Вот
Если вы используете GCC, вы можете установить глубину рекурсии шаблона с помощью -ftemplate-depth=X
, где X
Требуемая глубина:
g++ ...... -ftemplate-depth=750
Имейте в виду, что это не просто предел, который вы можете установить произвольно высоким. В какой-то момент вы столкнетесь с ОС и аппаратными ограничениями.
Что касается вашей действительной функции суммы, существует хорошо известное аналитическое решение для суммы первых N натуральных чисел.
Приложение B определяет рекомендуемые минимальные пределы; за рекурсивно вложенные шаблоны рекомендуемый минимальный предел — 1024. Похоже, что ваша реализация имеет ограничение 500; это по-прежнему соответствует требованиям, поскольку рекомендуемые минимальные ограничения являются лишь ориентировочными.
Ваш компилятор может иметь флаг командной строки или другую опцию для увеличения своего предела рекурсивно вложенного шаблона.
Самое простое решение — использовать нерекурсивный алгоритм; в твоем случае,
template<int N>
class Sum
{
public:
enum {value = N * (N + 1) / 2 };
};