## Fold expressions

* <!-- .element: class="fragment fade-in" --> Folding is a new way of handling argument package
* <!-- .element: class="fragment fade-in" --> It can be one or two arguments 
* <!-- .element: class="fragment fade-in" --> If it is two arguments we distinguish between
    * <!-- .element: class="fragment fade-in" --> left folding
    * <!-- .element: class="fragment fade-in" --> right folding
___

### Fold expressions - adding values

```C++
template <typename... Args>
int add(Args... args) {
    return (args + ...);
}

int main() {
    std::cout << add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) << '\n';
    std::cout << add() << '\n'; // Not compile!
}
```
<!-- .element: class="fragment fade-in" -->

```C++
55
```
<!-- .element: class="fragment fade-in" -->
___

### Fold expressions - adding values 

```C++
template <typename... Args>
int add(Args... args) {
    return (args + ... + 0);
}

int main() {
    std::cout << add(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) << '\n';
    std::cout << add() << '\n'; // OK
}
```
<!-- .element: class="fragment fade-in" -->

```C++
55
0
```
<!-- .element: class="fragment fade-in" -->
___

### Fold expressions - subtracting values

```C++
template <typename... Args>
int subR(Args... args) {
    return (args - ...);
}

template <typename... Args>
int subL(Args... args) {
    return (... - args);
}

int main() {
    // (1 - 2)
    std::cout << subR(1, 2) << '\n';           // -1
    // (1 - 2)
    std::cout << subL(1, 2) << '\n';           // -1
    // (1 - (2 - 3))
    std::cout << subR(1, 2, 3) << '\n';        //  2
    // ((1 - 2) - 3)
    std::cout << subL(1, 2, 3) << '\n';        // -4
    // (1 - (2 - (3 - 4)))
    std::cout << subR(1, 2, 3, 4) << '\n';     // -2
    // (((1 - 2) - 3) - 4)
    std::cout << subL(1, 2, 3, 4) << '\n';     // -8
    // (1 - (2 - (3 - (4 - 5))))
    std::cout << subR(1, 2, 3, 4, 5) << '\n';  //  3
    // ((((1 - 2) - 3) - 4) - 5)
    std::cout << subL(1, 2, 3, 4, 5) << '\n';  // -13
}
```

<!-- .slide: style="font-size: 0.69em" -->
___

### Fold expressions - make code work without parameters

Find a problem with the below code.
<!-- .element: class="fragment fade-in" --> 

```C++
template <typename... Args>
int subR(Args... args) {
    return (args - ... - 0);
}

template <typename... Args>
int subL(Args... args) {
    // What's wrong here???
    return (0 - ... - args);
}

int main() {
    // (1 - (2 - (3 - (4 - 5))))
    std::cout << subR(1, 2, 3, 4, 5) << '\n';
    // ((((1 - 2) - 3) - 4) - 5)
    std::cout << subL(1, 2, 3, 4, 5) << '\n';

    std::cout << subR() << '\n';
    std::cout << subL() << '\n';
}
```
<!-- .element: class="fragment fade-in" -->

```C++
3   // (1 - (2 - (3 - (4 - (5 - 0))))
-15 // (((((0 - 1) - 2) - 3) - 4) - 5)
0
0
```

<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.75em" -->
___

## How to demand minimum one variable

```C++
template<typename Value, typename... Values>
auto average(Value const& value, Values const&... values)
{
    return (value + ... + values) / (1. + sizeof...(values));
}

int main() {
    std::cout << average(1, 2, 3, 4) << '\n'; // print 2.5
    std::cout << average() << '\n' // NOT COMPILE!
}
```
___

## Calling member functions

```C++
template<typename... Args>
void loggStateForAll(const Args&... args)
{
    (..., args.loggState());
}

struct A {
    void loggState() const {
        std::cout << "StateA: good!\n";
    }
};

struct B {
    void loggState() const {
        std::cout << "StateB: bad!\n";
    }
};

int main() {
    loggStateForAll(A{}, B{}, A{}, B{});
    /* Will print
    StateA: good!
    StateB: bad!
    StateA: good!
    StateB: bad! */
}
```
<!-- .slide: style="font-size: 0.74em" -->
___

## Fold expressions - insert to container (1)

```C++
class Foo {
public:
    Foo(int num)
        : num_(num) {}

    int num() const { return num_; }

private:
    int num_;
};

template <typename... Args>
void emplaceAll(std::vector<Foo>& vec, Args... args) {
    (vec.emplace_back(args), ...);
}

int main() {
    std::vector<Foo> vec;
    emplaceAll(vec, 1, 2, 3, 4, 5, 6, 7);

    std::transform(cbegin(vec), cend(vec), std::ostream_iterator<int>(std::cout, " "),
                   [](const auto& foo) { return foo.num(); });
}
```
<!-- .element: class="fragment fade-in" -->

```C++
1 2 3 4 5 6 7
```
<!-- .element: class="fragment fade-in" -->

* <b>What with <code>(..., vec.emplace_back(args))</code>?</b>

<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.73em" -->
___

### Fold expressions - insert to container (2)

* <!-- .element: class="fragment fade-in" --> There is no right/left type of folding for one type of argument
    * <!-- .element: class="fragment fade-in" --> Unary right fold (fun(arg0) , (fun(arg1) , (fun(arg2) , ...)))
    * <!-- .element: class="fragment fade-in" --> Unary left fold (((fun(arg0) , fun(arg1)) , fun(arg2)) , ...
* <!-- .element: class="fragment fade-in" --> Only for binary folding, we can have different behavior
___

### Fold expressions - logic operators

```C++
template <typename... Args>
bool emplaceAll(std::set<int>& set, Args... args) {
    return (set.insert(args).second && ...);
}

int main() {
    std::set<int> set;
    emplaceAll(set, 1, 2, 3, 4, 5, 1, 6, 7);

    std::copy(cbegin(set), cend(set), std::ostream_iterator<int>(std::cout, " "));
}
```
<!-- .element: class="fragment fade-in" -->

```C++
1 2 3 4 5
```
<!-- .element: class="fragment fade-in" -->
<b>For bot way:</b>
<code>return (set.insert(args).second && ...);</code> 
<!-- .element: class="fragment fade-in" -->

<b>and</b>
<code>return (... && set.insert(args).second);</code>
<b>output will be the same</b>

<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.90em" -->
___

### Fold expressions - cooperation with STL algorithms

```C++
template <typename... Args>
bool HasAll(const std::vector<int>& vec, Args... args) {
    return ((std::find(cbegin(vec), cend(vec), args) != std::cend(vec)) && ...);
}

int main() {
    std::vector<int> vec{1, 2, 3, 4, 1, 2, 3, 5, 6, 7, 4};
    std::cout << std::boolalpha << HasAll(vec, 2, 4, 6) << '\n';
    std::cout << std::boolalpha << HasAll(vec, 2, 4, 6, 8) << '\n';
}
```
<!-- .element: class="fragment fade-in" -->

```C++
true
false
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.8em" -->
