This is a draft version of a MISRA C++ 202x rule proposed for public review.
MISRA Rule 19.0.2
Category: Required
Analysis Type: Decidable,Single Translation Unit
Rationale
Functions have a number of advantages over function-like macros, including:
- Function arguments and return values are type-checked;
- Function arguments are evaluated once, preventing problems with potential multiple side effects;
- Function names follow classical scoping rules;
- Functions can be overloaded and templatized;
- The address of a function can be passed to another function;
- Function calls can be inlined, providing the same performance characteristics as macros;
-
constexpr
functions can be evaluated at compile-time and may be used in all contexts where a compile-time constant is required;
- In many debugging systems, it is easier to step through execution of a function than a macro.
Exception
As it is not possible to implement equivalent behaviour within a function, a function-like macro may be defined if its definition includes any of
the following:
-
__LINE__
, __FILE__
or __func__
;
- The
#
or ##
operators.
Example
#define FUNC( X ) \
( ( X ) + ( X ) ) // Non-compliant
template< typename T >
constexpr auto func( T x ) // Possible alternative
{
return x + x;
}
The following examples are compliant by exception:
#define ID( name ) \
constexpr auto name = #name; // Compliant - use of #
#define TAG( name ) \
class name##Tag {}; // Compliant - use of ##
#define LOG( message ) \
log( __func__, message ); // Compliant - use of __func__
Copyright The MISRA Consortium Limited © 2023