Нескучное программирование (0х2). Обобщения условий
Теперь, когда сам алгоритм у нас есть, логично задать следующий вопрос: как сделать его обобщённым? Как превратить решение для целых чисел в алгоритм, который будет работать не только с unsigned, но и с другими типами данных?
Первый импульс обычно очень прямолинейный - хочется просто заменить конкретный тип на шаблонный параметр, условный T, и считать задачу решённой. Формально код действительно станет шаблонным, но почти сразу становится видно, что это лишь поверхностное обобщение, а не настоящее.
Возьмём, к примеру, проверку вида x < 0. Она имеет смысл только для знаковых числовых типов. Если T — беззнаковый тип, это выражение бессмысленно. Если T — матрица, вектор или пользовательский тип, такой операции может не существовать вовсе. Это первый сигнал о том, что алгоритм в своём текущем виде на самом деле жёстко привязан к конкретным типам данных.
Проблема нейтрального элемента
Другая, ещё более фундаментальная проблема связана с инициализацией результата. И если в простейшей версии алгоритма мы начинаем с единицы, что для целых и вещественных чисел выглядит естественно, то стоит выйти за пределы скалярной арифметики, и вопрос перестаёт быть тривиальным. Для матриц «единицей» является единичная матрица? А для комплексных чисел? А для пользовательских типов? Сам алгоритм не должен и не может знать, какое именно значение играет роль нейтрального элемента для умножения.

Можно попытаться решить эту проблему, введя некую глобальную функцию вроде identity(T), которая возвращает нейтральный элемент для типа Tи на первый взгляд это выглядит элегантно и даже будет работать (какое-то время), но на деле такое решение слишком жёсткое. Оно навязывает глобальное соглашение, которого может не существовать, и требует от каждого типа поддерживать нестандартный интерфейс, что сразу снижает универсальность алгоритма и делает его труднее интегрируемым в существующий код.