Шаблоны с параметрами по умолчанию — мощный механизм обобщённого программирования в C++.
История вопроса:
С шаблонов начиналась библиотека STL. Позже появилась возможность указывать значения по умолчанию для параметров как шаблонных функций, так и классов, чтобы сделать шаблоны более универсальными и поддерживать расширяемость кода.
Проблема:
Неочевидные конфликты возможны, когда существуют перегрузки обычных функций и шаблонных, а также неоднозначности при специализациях. Параметры по умолчанию в шаблонах могут повышать гибкость, но часто приводят к запутанным ошибкам компиляции.
Решение:
Лучше минимизировать число значений по умолчанию в шаблонах, особенно если есть пересечение с не-шаблонными версиями. Приоритет при вызове функций предпочитает точное совпадение с обычной функцией, а не шаблонную.
Пример кода:
template<typename T = int> T multiply(T a, T b = T(2)) { return a * b; } int multiply(int a, int b) { return a + b; }
Вызов multiply(5, 4) выберет функцию int multiply(int, int), а вызов multiply<>(5) вызовет шаблон, и b примет значение 2.
Ключевые особенности:
Можно ли объявить параметры по умолчанию в очередном определении шаблонной функции?
Нет, значение по умолчанию можно указывать только в одном месте (обычно в объявлении), иначе будет ошибка компиляции.
Что произойдёт при неоднозначности между шаблоном и не-шаблонной функцией? Как компилятор выбирает, что вызывать?
Компилятор всегда отдаст предпочтение не-шаблонной функции, если она точно подходит по аргументам. Шаблонная вызовется только в случае отсутствия точного совпадения.
Можно ли указывать значения по умолчанию для не-типа параметра шаблона (например, для числа)?
Да, например:
template<typename T, int N = 8> class Array { T data[N]; };
Негативный кейс
Объявлены и шаблонная, и не-шаблонная функция с совпадающими параметрами и значениями по умолчанию. В одном модуле вызов работает как задумано, а в другом неожиданно выбирается не та версия функции.
Плюсы:
Минусы:
Позитивный кейс
Для пересекающихся конфигураций объявлены явно различные именования для шаблонных и не-шаблонных функций, значения по умолчанию только у одной из версий.
Плюсы:
Минусы: