C++, почему расширение моего шаблона привело к переполнению стека компилятора?

Я пробовал шаблонное метапрограммирование и написание функции для вычисления мощности базы, например 3^2=9

template<int N>
int Tpow(int base){return N==0?1:base*Tpow<N-1>(base);}
int main()
{
    int r3=Tpow<3>(2);
    return 0;
}

Всего несколько строк, но он вылетает как gcc, так и clang. Где я ошибся? Благодарю.

2 ответа

Решение

Решение: Вы должны специализировать свой шаблон для N, равного 0. Как:

template<>
int Tpow<0>(int base){return 1;}

Теперь, когда у вас есть это, вы также можете оптимизировать свой оригинальный шаблон следующим образом:

template<int N>
int Tpow(int base){return base*Tpow<N-1>(base);}

потому что вы знаете, что обрабатывать случай N равен 0.

Пояснение: Ваш компилятор в основном делает это: Он видит

int r3=Tpow<3>(2);

и делает функцию для 3 в качестве переменной шаблона, например, так

int Tpow_3(int base){return 3==0?1:base*Tpow<3-1>(base);}

а затем он должен сделать функцию для 2 в качестве переменной шаблона, например, так

int Tpow_2(int base){return 2==0?1:base*Tpow<2-1>(base);}

и это продолжается и продолжается, потому что компилятор не заботится о вашем 0==0?... еще.

Компилятор должен скомпилировать все тело функции: он не может полагаться на троичное условное выражение для компиляции только одной стороны. Таким образом, нет никакого блока на рекурсии.

(С использованием constexpr C++11 тоже не поможет).

Чтобы решить эту проблему, вам нужно специализировать функцию для случая N = 0.

Другие вопросы по тегам