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
myObjis wrapped instd::refwhen 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
constfunction call operator that does not modify the state of the predicate object. For example, in this code snippet,predModifiesdefines a call operator that modifieselemPositionbefore checking the equality whereaspredDoesNotModifychecks only the equality ofvarwithout 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
thispointer 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::refstd::crefstd::functionstd::bindstd::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