# Chapter 21 - Notes

## Function Objects&#x20;

**Function objects** are simply objects that work as functions.&#x20;

At the implementation level, **function objects** are objects of a class that implement `operator()`.&#x20;

```cpp
struct GreetFunction {
    void operator() {
        std::cout << "Hello!" << std::endl;
    }
}
```

Regular functions and function pointers can also be used as function objects.&#x20;

Although objects of a class implementing `operator()` has the added benefit of being able to contain 'state' in its member attributes. This has several useful properties when used with STL algorithms.&#x20;

* Unary function - a function called with **one argument**.
* Binary function - a function called with **two arguments**.&#x20;

Functions whose return types are `bool` are also referred to as **predicates**; these are useful for "decision making" algorithms such as `std::find` (does this element match my predicate?) and `std::sort`(should I switch these elements?).

## Parameter Type&#x20;

* The `auto` keyword is useful for creating function pointers.&#x20;
* The actual type of a function is `<return_type>(*<variable_name>)(<parameter_type>, <parameter_type>, ...)`
* The declaration `void(*hello_function)()` defines a function variable:
  * called `hello_function`
  * returns a `void` type&#x20;
  * and takes no parameters&#x20;

## Unary Functions&#x20;

Unary functions are functions invoked with **one parameter**.

Such function objects are useful for STL algorithms such as `std::for_each`.&#x20;

### Example&#x20;

Create a `ListPrinter` unary function object that prints a particular element to the screen as a numbered list, incrementing the list each time it is invoked.

```cpp
int main() {
    auto print = ListPrint();
    std::vector<std::string> names {"Alice", "Bob", "Charlie"};
    
    for_each(names.begin(),  // Start of range
             names.end(),  // End of range
             print);  // Unary function object 
}
```

Which should output:

```cpp
1. Alice
2. Bob
3. Charlie 
```

## Unary Predicate&#x20;

Unary predicates are unary functions whose return types are `bool`.&#x20;

Such function objects are useful for STL algorithms such as `std::find_if`, `std::remove_if`, `std::partition`, etcetera.&#x20;

### Example&#x20;

Create a `IsDivisibleBy` unary function predicate object - this will be a struct with a constructor accepting an integer value, and an `operator()` implementation accepting a single argument, and returning true if the argument is perfectly divisible by the value passed to the constructor.&#x20;

```cpp
int main() {
    auto isDivisble = IsDivisibleBy(5);
    
    int numberToCheck;
    std::cin >> numberToCheck;
    if (isDivisible(numberToCheck)) {
        std::cout << numberToCheck << " is divisible by 5" << std::endl;
    } else {
        std::cout << numberToCheck << " is not divisible by 5" << std::endl;
    }
}
```

Use the function predicate object with the `std::find_if` algorithm.&#x20;

## Binary Functions&#x20;

Binary functions are functions invoked with **two parameters**.

Such functions can be used for various arithmetic activity, such as addition, multiplication, subtraction, etcetera. For example with use with the `std::transform` algorithm to perform a pairwise operation between two containers.&#x20;

### Example&#x20;

```cpp
template <typename T>
struct Multiply {
    T operator() (const T& first, const T& second) {
        return first * second;
    }
}
```

```cpp
int main() {
    std::vector<int> vectorInt1 = {1, 2, 3, 4, 5};
    std::vector<int> vectorInt2 = {10, 20, 30, 40, 50};
    
    std::vector<int> result;
    result.resize(vectorInt2.size());
    
    std::transform(vectorInt1.begin(),  // Source start range 
                   vectorInt1.end(),  // Source end range
                   vectorInt2.begin(),  // Target start range
                   result.begin(),  // Result start range
                   Multiply<int>())  // Binary function to be applied pairwise 
   
    for (auto num: result) {
        std::cout << num << " ";
    }
    std::cout << std::endl;
}
```

`Multiply::operator()` is invoked for every pairwise element in the two vectors, the result of the operation is stored in the `result` vector.&#x20;

## Binary Predicate

Binary predicates are binary functions whose return types are `bool`.&#x20;

Such functions are useful for STL algorithms such as `std::sort`.&#x20;

### Example&#x20;

Create a binary predicate class that performs a comparison of two strings, returning true if the first string argument is alphabetically less than the second string.&#x20;

Extend this predicate to perform a **case-insensitive sort**, by first reducing both strings to lowercase then performing the same comparison.

Use this binary predicate with the `std::sort` algorithm to sort a dynamic array of strings of varying case.
