Templates with default parameters are a powerful mechanism for generic programming in C++.
Background:
The STL library started with templates. Later, the ability to specify default values for parameters in both template functions and classes appeared to make templates more versatile and maintain code extensibility.
Problem:
Non-obvious conflicts can occur when there are overloads of regular functions and templates, as well as ambiguities in specializations. Default parameters in templates can increase flexibility, but often lead to confusing compilation errors.
Solution:
It is better to minimize the number of default values in templates, especially if there is overlap with non-template versions. Function call priority prefers an exact match with a regular function over a template.
Code example:
template<typename T = int> T multiply(T a, T b = T(2)) { return a * b; } int multiply(int a, int b) { return a + b; }
Calling multiply(5, 4) will choose the function int multiply(int, int), while calling multiply<>(5) will invoke the template, and b will take the value 2.
Key features:
Can you declare default parameters in a subsequent definition of a template function?
No, the default value can only be specified in one place (usually in the declaration), otherwise there will be a compilation error.
What happens in case of ambiguity between a template and a non-template function? How does the compiler choose what to call?
The compiler will always prefer the non-template function if it exactly matches the arguments. The template will only be called if there is no exact match.
Can default values be specified for non-type template parameters (e.g., for a number)?
Yes, for example:
template<typename T, int N = 8> class Array { T data[N]; };
Negative case
Both a template and a non-template function are declared with matching parameters and default values. In one module the call works as intended, while in another an unexpected version of the function is selected.
Pros:
Cons:
Positive case
For overlapping configurations, clearly different naming is declared for template and non-template functions, with default values only on one of the versions.
Pros:
Cons: