Why is this an issue?
This is a draft version of a MISRA C++ 202x rule proposed for public review.
MISRA Rule 16.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
Resources
Related rules
- S960 targets the same defect as this rule but for a non-mission-critical context.
- S6190 proposes a replacement for
__FILE__
, __LINE__
and __func__
in C++20
- M23_212: MISRA C++ 2023 Rule 16.3.1 - The
#
and ##
preprocessor operators should not be used
External coding guidelines