This rule is part of MISRA C++:2023.
Usage of this content is governed by Sonar’s terms and conditions. Redistribution is
prohibited.
Rule 28.3.1 - Predicates shall not have persistent side effects [1]
[algorithms.requirements]
[alg.sorting]
Category: Required
Analysis: Undecidable,System
Amplification
When a template parameter is named Compare, Predicate, or BinaryPredicate in the C++ Standard Library, every
callable passed as an argument of that type is a predicate.
In addition to not having persistent side effects [1], if the predicate is a function object, its
operator() shall be declared const.
Note: the operator() of a lambda closure is const unless the lambda is declared
mutable.
Rationale
It is implementation defined if the predicate used by an algorithm will be copied. The state of such a predicate may
therefore unexpectedly be different if a copy is made. Additionally, most algorithms do not specify in which order the predicates will be
invoked, or on which objects. This makes it very difficult to implement a sensible predicate with mutable internal state.
Ideally, a tool will provide a mechanism that allows the identification of additional predicates in order to include them in the analysis
scope of this rule.
Example
bool bar( std::vector< int32_t > & v, int32_t & count )
{
return std::any_of( v.begin(), v.end(),
[&count]( int32_t i ) // Non-compliant
{
if ( i == 3 )
{
++count; // Persistent side effect
return true;
}
return false;
} );
}
struct Comp
{
bool operator()( int32_t a, int32_t b ) // Non-compliant - not const
{
return a > b;
}
};
std::set< int32_t, Comp > mySet;
Glossary
[1] Persistent side effect
A side effect is said to be persistent at a particular point in execution if it might have an effect on the execution state at
that point. All of the following side effects are persistent at a given point in the program:
- Modifying a file, stream, etc.;
- Modifying an object, including via a pointer or reference;
- Accessing a volatile object;
- Raising an exception that transfers control outside of the current function.
When a function is called, it may have side effects. Modifying a file or accessing a volatile object are persistent as viewed by
the calling function. However any objects modified by the called function, whose lifetimes have ended by the time it returns, do not affect the
caller’s execution state. Any side effects arising from modifying such objects are not persistent from the point of
view of the caller.
The determination of whether a function has persistent side effects takes no consideration of the possible values for parameters or other
non-local objects.
Copyright The MISRA Consortium Limited © 2023