ProgrammingC++ Developer, Lead Developer

How do function and class templates with default parameters work? What nuances are there in their usage, and what to do in case of conflicts between template and non-template functions?

Pass interviews with Hintsage AI assistant

Answer.

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:

  • Default values are declared only in the first declaration/definition of the template.
  • Regular functions take priority over templates when signatures match.
  • Default values for template parameters are applied only when they are absent in the explicit call.

Trick questions.

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]; };

Typical mistakes and anti-patterns

  • Declaring default values simultaneously in multiple places.
  • Implicit ambiguity between template and regular functions.
  • Excessive use of default parameters, complicating code readability and debugging.

Real-life example

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:

  • Convenient to call without specifying the type.

Cons:

  • Non-obvious errors and confusing call logic.

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:

  • Explicit behavior.
  • No call collisions.

Cons:

  • Slightly more code for maintaining function versions.