AUTOSAR C++14 Rule A25-1-1
Non-static data members or captured values of predicate function objects that are state related to this object's identity shall not be copied
Since R2022a
Description
Rule Definition
Non-static data members or captured values of predicate function objects that are state related to this object's identity shall not be copied.
Rationale
Predicate function objects take a single argument and use that argument to return a value that is testable as a boolean (true or false). Standard Template Library (STL) algorithms that accept a predicate function object may, depending on the algorithm implementation, make a copy of the function object. The invocation of the copy might cause unexpected results.
For example, suppose that you use an algorithm to remove one element from a list. To determine the element to remove, the algorithm uses a predicate function object that modifies a state related to the function object identity each time the function object is called. You might expect the predicate object to return true only once. If the algorithm makes a copy of the predicate object, the state of the copy is also modified and the copy returns true a second time, removing a second element from the list.
To avoid unexpected results, consider one of the following:
Wrap the predicate function object in a
std::reference_wrapper<T>
before you pass it to the algorithm. If the wrapper object is copied, all copies refer to the same underlying predicate function object.For example, in this code snippet, predicate function object
myObj
is wrapped instd::ref
when passed tostd::remove_if
.class predObj { // Defines function object that modifies its state }; void func() { std::vector<int> v{0, 1, 2, 3, 4, 5}; // predObj myObj; v.erase(std::remove_if(v.begin(), v.end(), std::ref(myObj)), v.end()); //.... }
Implement a
const
function call operator that does not modify the state of the predicate object. For example, in this code snippet,predModifies
defines a call operator that modifieselemPosition
before checking the equality whereaspredDoesNotModify
checks only the equality ofvar
without modifying it.class predModifies : public std::unary_function<int, bool> { public: predModifies() : elemPosition(0) {} bool operator()(const int &) const { return (++elemPosition) == 3; } //call operator modifies elemPosition private: mutable size_t elemPosition; }; class predDoesNotModify: public std::unary_function<int, bool> { public: bool operator()(const int& var) const { return var == 3; } //call operator does not modify state of object };
Polyspace Implementation
Polyspace® flags violations of this rule when the following conditions are true:
You use a STL algorithm that takes a predicate function object. For a full list of STL algorithms, see Algorithms library.
The state of the function object is modified, where the state is one of the following:
The
this
pointer if the predicate object is an instance of a class that defines a function call operatoroperator()
.A captured-by-copy value if the predicate object is a lambda function. A lambda function that captures values by reference is compliant.
A function object state is modified if it is written to or if a non-const
method is called on it. For example, in this code snippet, non-const method
increment()
modifies the state elemPosition
of
operator()
:
#include <functional> #include <vector> #include <algorithm> class myPred : public std::unary_function<int, bool> { public: myPred(): elemPosition(0) {} void increment() {++elemPosition;} // Non-const method bool operator()(const int&) // function call operator { increment(); // method called on state elemPosition return elemPosition == 3; } private: size_t elemPosition; }; void func(std::vector<int> v) { std::remove_if(v.begin(), v.end(), myPred()); // Noncompliant }
Polyspace does not flag function objects that are wrapped in these:
std::ref
std::cref
std::function
std::bind
std::not1
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: Algorithms library |
Category: Required, Automated |
Version History
Introduced in R2022a