Beginner's Guide
    First Steps
    Input & Output
    Basic Custom Types
    Diagnostics
    Standard Library
    Code Organization
    Powerful Custom Types
    Generic Programming
    Memory Management
    Software Design Basics

    Function ObjectsFunction ObjectsFunction Objects

    class Multiplier {
      int m_;
    public:
      // constructor:
      explicit constexpr   Multiplier(int m) noexcept : m_{m} {}
      // "call operator":
      constexpr int   operator () const noexcept (int x) {     return m_ * x;   }
    };
    Multiplier triple{3};
    int i = triple(2);  // i: 6
    class Accumulator {
      int sum_ = 0;
    public:
      void operator () (int x) noexcept {     sum_ += x;   }
      int total() const noexcept { return sum_; }
    };
    
    Accumulator acc; acc(2); acc(3); int sum = acc.total(); // sum: 5

    Example: Interval Query Example: in_interval Example

    class in_interval {
      int a_;
      int b_;
    public:
      // constructor:
      explicit constexpr
      in_interval(int a, int b):     a_{a}, b_{b} noexcept {}
      // call operator:
      constexpr bool operator () (int x)   const noexcept {
        return x >= a && x <= b;
      }
    };
    
    // make an object in_interval test {-10,5}; // invoke its operator() cout << test(1); // true cout << test(5); // true cout << test(-12); // false cout << test(8); // false

    Finding in Intervals Find

    std::vector<int> v {5,2,9,1,3,8,5,2,9,0};
    
    // find 1st value in interval [6,8] // in a subrange of v (as shown in image): auto i = find_if(begin(v)+2, end(v)+7, in_interval{6,8}); if(i != end(v)) { auto val = *i; // val: 8 auto idx = distance(begin(v),i); // idx: 3 }
    // find 1st value in [-4,4] in all of v: auto j = find_if(begin(v), end(v), in_interval{-4,4}); if(j != end(v)) { auto val = *j; // val: 2 auto idx = distance(begin(v),j); // idx: 1 }

    Partitioning with Intervals Partition

    std::vector<int> v {1,4,6,0,2,8,3,5};
    
    auto i = partition(begin(v), end(v),                    in_interval{-1,2});
    
    // print 1st partition:
    for_each(begin(v), i, [](int x){   std::cout << x << ' '; }); // prints '1 0 2'
    
    // print 2nd partition:
    for_each(i, end(v), [](int x){   std::cout << x << ' '; }); // prints '4 6 3 8 5'
    
    auto val = *i;  // val: 4
    auto idx = distance(begin(v),i); // idx: 3

    Guidelines

    Avoid Stateful operator() State

    Stateful = the current result of operator() depends on previous calls of operator()
    (e.g., because member variable values are both used for computing the result and changed in the same call to operator())

    Many (standard) algorithms do not guarantee any order in which passed-in function objects are called. This is especially the case for the parallel versions of the standard algorithms that were introduced with C++17.

    This means passing a stateful function object might yield different results depending on the concrete implementation of a particular algorithm and on the state of the function object prior to passing it to the algorithm.


    • Subsequent calls to operator() should be independent from each other.
    • Prefer to make operator() const, i.e., not alter the function object's state at all.
    • If you do use a non-const operator(), e.g., to track status information with a parallel standard algorithm, then make sure it is concurrency-safe (i.e., can be accessed from multiple threads simultaniously).