 
                            ...
Marking the function call operator as const is beneficial, but insufficient, because data members with the mutable storage class specifier may still be modified within a const member function.
...
Compliant Solution (std::reference_wrapper)
This compliant solution wraps uses std::ref to wrap the predicate in a std::reference_wrapper<T> object, ensuring that copies of the wrapper object all refer to the same underlying predicate object.
| Code Block | ||||
|---|---|---|---|---|
| 
 | ||||
| #include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>
#include <vector>
  
class MutablePredicate : public std::unary_function<int, bool> {
  size_t timesCalled;
public:
  MutablePredicate() : timesCalled(0) {}
  bool operator()(const int &) {
    return ++timesCalled == 3;
  }
};
 
template <typename Iter>
void print_container(Iter b, Iter e) {
  std::cout << "Contains: ";
  std::copy(b, e, std::ostream_iterator<decltype(*b)>(std::cout, " "));
  std::cout << std::endl;
}
 
void f() {
  std::vector<int> v{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  print_container(v.begin(), v.end());
  MutablePredicate mp;
  v.erase(std::remove_if(v.begin(), v.end(), std::ref(mp)), v.end());
  print_container(v.begin(), v.end());
} | 
The above compliant compliant solution demonstrates using a reference wrapper over a functor object but can similarly be used with a stateful lambda. The code produces the expected results, where only the third element is removed.
...
Using a predicate function object that contains state can produce unexpected values.
| Rule | Severity | Likelihood | 
|---|
| Detectable | Repairable | Priority | Level | 
|---|---|---|---|
| CTR58-CPP | Low | Likely | 
| Yes | No | 
| P6 | 
| L2 | 
Automated Detection
| Tool | Version | Checker | Description | 
|---|
| Helix QAC | 
 | C++3225, C++3226, C++3227, C++3228, C++3229, C++3230, C++3231, C++3232, C++3233, C++3234 | |||||||
| Parasoft C/C++test | 
 | CERT_CPP-CTR58-a | Make predicates const pure functions | ||||||
| Polyspace Bug Finder | 
 | CERT C++: CTR58-CPP | Checks for function object that modifies its state (rule fully covered). | 
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Bibliography
| [ISO/IEC 14882-2014] | Subclause 25.1, "General" | 
| [Meyers | 
| 2001] | Item 39, "Make Predicates Pure Functions" | 
...
...