MISRA C++:2023 Rule 17.8.1
Description
Rule Definition
Function templates shall not be explicitly specialized.
Rationale
Explicit specialization of function templates can cause unexpected issues with overload resolution in C++. Overload resolution:
First searches for a non-template, plain-old-function that has a matching parameter list.
If such a function is not available, overload resolution selects the closest matching function template.
After a function template is selected, the compiler searches for a suitable specialization of the selected template.
Specializing a template does not change the order of the overload resolution process, which can result in confusing and unexpected behavior. Consider this code snippet:
//(a) base template template<class T> void f( T ); //(b) specialization of (a) template<> void f<>(int*); //... //(c) overloads (a) template<class T> void f( T* ); //... main(){ int *p; f( p ); }
f()
is called with an int*
in
main()
, you might expect the specialization for
int*
, marked (b), to be called. The compiler resolves the call to
f()
as follows:
The compiler searches for a plain-old-function with input type
int*
.Because there is no such function, the compiler searches for a function template that has the closest matching parameter list.
The template (c), which takes a generic pointer as input, is the closest match for
f(int*)
.The template (c) is not specialized. The overload resolution process stops and calls the template in (c).
Even though a specialized template for int*
type input is
defined in (b), the function call resolves to the template in (c) instead, which can be
unexpected.
When you specialize an overloaded function template, which among the overloaded templates gets specialized depends on the order of declaration. Consider the code snippet:
//(a) template <typename T> void F1(T t){} //(b) template <typename T> void F1(T* p){} //(x): Specialization of template template <> void F1<>(uint16_t* p){}
//(a) template <typename T> void F1(T t){} //(x): Specialization of template template <> void F1<>(uint16_t* p){} //(b) template <typename T> void F1(T* p){}
To avoid confusing code and unexpected behavior, avoid specializing function templates.
If you must specialize a function template, then write a single function template that
delegates to a class template. For example, in this code, a function template
f()
delegates to the class
f_implementation
.
template<class T> class f_implementation; template<class T> void f( T t ) { FImpl<T>::f( t ); //Don't specialize function template } template<class T> class f_implementation { static void f( T t ); // Specializing class templates is permissible. }
Polyspace Implementation
If you explicitly specialize a function template, Polyspace® flags the function template.
Troubleshooting
If you expect a rule violation but Polyspace does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.
Examples
Check Information
Group: Templates |
Category: Required |
Version History
Introduced in R2024b