Static function template and MISRA C ++

The following function template with specializations should only be used in one file .cpp

, so Id must do it static

. The following code compiles (no warnings) using both MS Visual C ++ 2008 and GCC 4.8.1 and works as intended. (Adding static

to the beginning of lines 5 and 11 will result in a GCC error, but not MSVC.)

 1  template <class T>
 2  static bool foo(const T param);
 3
 4  template <>
 5  bool foo<int>(const int param)
 6  {
 7      return doSomethingWithInt(param);
 8  }
 9
10  template <>
11  bool foo<bool>(const bool param)
12  {
13      return doSomethingWithBool(param);
14  }

      

However, the MISRA C ++ checker complains:

  • (MISRA2008.3-3-2) Apply static keyword to declaration 'foo' (1)
  • (MISRA2008.3-3-2) Apply static keyword to declaration 'foo' (5)
  • (MISRA2008.2-10-5-b) Identifier 'foo' reused (5)
  • (MISRA2008.3-3-2) Apply static keyword to declaration 'foo' (11)
  • (MISRA2008.2-10-5-b) Identifier 'foo' reused (11)

I tried to figure out what was wrong and found a hint of a standard C ++ quote :

For a function call that depends on a template parameter, if the function name is an unqualified identifier but not a template identifier, candidate functions are found using normal search rules (3.4.1, 3.4.2), except that:

  • For the search part using unqualified name lookup (3.4.1), only externally linked function declarations from the template are the definition context.

Does this mean that compilers drop the BOM static

and there is no way to actually create static function templates in C ++ 03?

+3


source to share


1 answer


Explicit specializations allow you to modify the definition of a function (or class) based on the template arguments with which the template is specialized. They are not "new declarations".

GCC correctly warns against using static

explicit specializations 7.1.1 / 1:

A storage class specifier does not need to be specified in an explicit specialization (14.7.3) or an explicit instance directive (14.7.2).

Hence, it seems that the advice from your MISRA check for applying "static" is not correct for 5 and 11, and I would also question that foo

it is somehow reused. There is only one entity foo

that has different definitions.

The internally linked function is not visible outside this translation unit. Explicit specialization is considered only after the main template has been selected using overload resolution.

Consider the following:

template <typename T>
void f (T);              // #1

template <>
void f<int*> (int*);     // #2

template <typename T>
void f (T*);             // #3

void b() {
  int * i;
  f(i);                  // Calls #3
}

      

The search f

finds two patterns, # 1 - f(T)

and # 3 - f(T*)

. T

output int*

for # 1 and int

for # 3 (14.8.2). Overload resolution comes with specializations # 1 → f(int*)

and # 3 → f(int*)

. Not the best match, so a partial ordering occurs (14.5.6.2). The result of the partial ordering is that # 3 is more specialized than # 1. Therefore, the compiler chooses # 3 as the best match. NB: Explicit specialization did not participate in any of the above steps.



If there was no # 3. Then # 1 would be chosen as the best match in overload resolution. The compiler then looks for a list of specialties. The list of output arguments int*

matches the list of arguments used in explicit specailziation, and therefore definition # 2 is called.

Regarding the quoted paragraph:

  • For the search part using unqualified name lookup (3.4.1), only function declarations with external linkage from the context of the template definition were found.

This limitation came about when templates could be exported (C ++ '03 14/6). The idea was to allow templates to be defined outside the current translation unit. This search constraint would help ensure that changing the exported non-exported template would not result in another program of values.

As for your question about what this means for static function templates and C ++ '03, the reality is actually that only one compiler vendor I know has ever implemented exported templates in full. Chances are good that most compiler vendors have been following C ++ 11's advice for a long time anyway. In terms of MISRA compliance, the best option is to follow the metal guidelines for your question. Place the template in an unnamed namespace.

In C ++ '03, names will be overwhelming because of the translation unit, and for C ++ '11 they will have an implicit internal linkage (3.5 / 4):

An unnamed namespace, or a namespace declared directly or indirectly in an unnamed namespace, an internal link.

0


source







All Articles