## Small features
<!-- .slide: data-background="#ccc" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## operator<=>

Since C++20 we don't need to define all comparison operators for custom structures. Instead of `==`, `!=`, `>`, `<`, `<=`, `>=` we can simply write one universal comparator `<=>`.

```C++
struct Student {
    auto operator<=>(const Student& other) const = default;

    std::string name_;
    double average_;
    int index_;
};

int main() {
    Student student1{.name_ = "Mateusz", .average_ = 4.67, .index_ = 456123};
    Student student2{.name_ = "Michał", .average_ = 4.57, .index_ = 123456};
    Student student3{.name_ = "Marcelina", .average_ = 4.67, .index_ = 321456};
    Student student4{.name_ = "Mirosław", .average_ = 4.47, .index_ = 135246};

    std::cout << "student1 < student2 ? " << (student1 < student2) << '\n';   // True
    std::cout << "student1 < student3 ? " << (student1 < student3) << '\n';   // False
    std::cout << "student1 < student4 ? " << (student1 < student4) << '\n';   // True
    std::cout << "student2 < student3 ? " << (student2 < student3) << '\n';   // False
    std::cout << "student2 < student4 ? " << (student2 < student4) << '\n';   // True
    std::cout << "student3 < student4 ? " << (student3 < student4) << '\n';   // True
    std::cout << "student1 == student1 ? " << (student1 == student1) << '\n'; // True
}
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.80em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## How it works?

First, we need to understand how the compiler treats the structure `Student`. This structure has 3 fields: `name`, `average`, and `index`. During the comparison, the first field is to compare if both values are the same, if true we reach a second one, and so on. In other words, first different fields decide which structure is lower.

```C++
int main() {
    Student student1{.name_ = "Mateusz", .average_ = 4.67, .index_ = 456123};
    Student student2{.name_ = "Mateusz", .average_ = 4.67, .index_ = 123456};
    Student student3{.name_ = "Mateusz", .average_ = 4.57, .index_ = 321456};
    Student student4{.name_ = "Mateusz", .average_ = 4.57, .index_ = 135246};

    std::cout << "student1 > student2 ? " << (student1 > student2) << '\n';   // T (higher index)
    std::cout << "student1 > student3 ? " << (student1 > student3) << '\n';   // T (higher average)
    std::cout << "student1 > student4 ? " << (student1 > student4) << '\n';   // T (higher average)
    std::cout << "student2 > student3 ? " << (student2 > student3) << '\n';   // T (higher average)
    std::cout << "student2 > student4 ? " << (student2 > student4) << '\n';   // T (higher average)
    std::cout << "student3 > student4 ? " << (student3 > student4) << '\n';   // T (higher index)
    std::cout << "student1 == student1 ? " << (student1 == student1) << '\n'; // T (the same person)
}
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.80em" -->

___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## But I don't want to compare some fields...

When you don't want to compare one or more fields, you need to write your own comparator.

```C++
struct Student {
    std::partial_ordering operator<=>(const Student& other) const {
        if (const auto res = average_ <=> other.average_; res != 0) {
            return res;
        }
        return name_ <=> other.name_;
    }
};

int main() {
    Student student1{.name_ = "Mateusz", .average_ = 4.67, .index_ = 456123};
    Student student2{.name_ = "Mateusz", .average_ = 4.67, .index_ = 123456};
    Student student3{.name_ = "Mateusz", .average_ = 4.57, .index_ = 321456};

    std::cout << "student1 > student2 ? " << (student1 > student2) << '\n';    // T (higher index)
    std::cout << "student1 < student3 ? " << (student1 < student3) << '\n';    // F (lower average)
    // This line do not compile :(
    std::cout << "student1 == student1 ? " << (student1 == student1) << '\n';  // T (the same person)
}
```
<!-- .element: class="fragment fade-in" -->

But why do we wrote`std::partial_ordering` instead of `auto`? It's because we compare two floating point values. I know that earlier we wrote `auto operator<=>` and it's worked, but this was fully generated by the compiler. If we are writing it manually and we need to specify what result we return. 
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.74em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## Types of ordering

* <!-- .element: class="fragment fade-in" --> <code>strong_ordering</code>: a total ordering, where equality implies substitutability (that is (a <=> b) == strong_ordering::equal implies that for reasonable functions f, f(a) == f(b). “Reasonable” is deliberately underspecified – but shouldn’t include functions that return the address of their arguments or do things like return the capacity() of a vector, etc. We want to only look at “salient” properties – itself very underspecified, but think of it as referring to the value of a type. The value of a vector is the elements it contains, not its address, etc.). The values are strong_ordering::greater, strong_ordering::equal, and strong_ordering::less.
* <!-- .element: class="fragment fade-in" --> <code>weak_ordering</code>: a total ordering, where equality actually only defines an equivalence class. The canonical example here is case-insensitive string comparison – where two objects might be weak_ordering::equivalent but not actually equal (hence the naming change to equivalent).
* <!-- .element: class="fragment fade-in" --> <code>partial_ordering</code>: a partial ordering. Here, in addition to the values greater, equivalent, and less (as with weak_ordering), we also get a new value: unordered. This gives us a way to represent partial orders in the type system: 1.f <=> NaN is partial_ordering::unordered.
<!-- .slide: style="font-size: 0.85em" -->

___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## Ok but what with operator==

beacuse we have custom `operator<=>`, which return `std::partial_ordering` we can't use `operator==`. We need to provide own `operator==`. And we can do this by default (compare all fileds) or manually (compare specific fileds).

```C++
struct Student {
    std::partial_ordering operator<=>(const Student& other) const {
        if (const auto res = average_ <=> other.average_; res != 0) {
            return res;
        }
        return name_ <=> other.name_;
    }

    bool operator==(const Student& other) const {
        return name_ == other.name_ && average_ == other.average_;
    }

    std::string name_;
    double average_;
    int index_;
};

int main() {
    Student student1{.name_ = "Mateusz", .average_ = 4.67, .index_ = 456123};
    Student student2{.name_ = "Mateusz", .average_ = 4.67, .index_ = 123456};

    std::cout << "student1 > student2 ? " << (student1 > student2) << '\n';    // T (higher index)
    std::cout << "student1 == student1 ? " << (student1 == student1) << '\n';  // T (the same person)
}
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.74em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

We can also decide to use default `operator==` and this also work!

```C++
struct Student {
    std::partial_ordering operator<=>(const Student& other) const {
        if (const auto res = average_ <=> other.average_; res != 0) {
            return res;
        }
        return name_ <=> other.name_;
    }

    bool operator==(const Student&) const = default;

    std::string name_;
    double average_;
    int index_;
};

int main() {
    Student student1{.name_ = "Mateusz", .average_ = 4.67, .index_ = 456123};
    Student student2{.name_ = "Mateusz", .average_ = 4.67, .index_ = 123456};

    std::cout << "student1 > student2 ? " << (student1 > student2) << '\n';    // T (higher index)
    std::cout << "student1 == student1 ? " << (student1 == student1) << '\n';  // T (the same person)
}
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.74em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## More about partial_ordering

To sum up, if we compare 2 floating point values, the result is `std::partial_ordering`. We can't use `operator==` in such a case. This makes sense, but when do we also need this type of order? Let's check the below example:

```C++
struct Student {
    std::partial_ordering operator<=>(const Student& other) const {
        if (!name_ || !other.name_) {
            return std::partial_ordering::unordered;
        }
        if (const auto res = name_ <=> other.name_; res != 0) {
            return res;
        }
        return index_ <=> other.index_;
    }
    bool operator==(const Student&) const = default;

    std::optional<std::string> name_;
    double average_;
    int index_;
};

int main() {
    Student student1{.name_ = "Mateusz", .average_ = 4.67, .index_ = 456123};
    Student student2{.name_ = std::nullopt, .average_ = 4.67, .index_ = 123456};

    std::cout << "student1 > student2 ? " << (student1 > student2) << '\n';    // F (second student doesn't has name!)
    std::cout << "student1 < student2 ? " << (student1 < student2) << '\n';    // F (second student doesn't has name!)
    std::cout << "student1 != student2 ? " << (student1 != student2) << '\n';  // T (here we use operator== not <=>)
    std::cout << "student1 == student2 ? " << (student1 == student2) << '\n';  // F (here we use operator== not <=>)
    std::cout << "student2 == student2 ? " << (student2 == student2) << '\n';  // T (here we use operator== not <=>)
}
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.70em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## Ok but how <=> exactly works?

Each type or ordering could represent one of those 3 values (partial could also has `unordered`):

* std::strong_ordering::less    / weak_ordering::less       / std::partial_ordering::less
* std::strong_ordering::equal   / weak_ordering::equivalent / std::partial_ordering::equivalent
* std::strong_ordering::greater / weak_ordering::greater    / std::partial_ordering::greater

We can simply compare them:
<!-- .element: class="fragment fade-in" -->
```C++
int val1(1234);
int val2(12345);
auto res = val1 <=> val2;
if (res < 0) 
    std::cout << "val1 < val2" << std::endl;
else if (res == 0) 
    std::cout << "val1 == val2" << std::endl;
else if (res > 0) 
    std::cout << "val1 > val2" << std::endl;
```
<!-- .element: class="fragment fade-in" -->
This is implicity generated by compiler. For instance `a > b` is converted to `(a <=> b) > 0`
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.85em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## Finally, something about weak ordering 

Weak ordering is returned when does not imply substitutability: if a is equivalent to b, f(a) may not be equivalent to f(b), where f denotes a function that reads only comparison-salient state that is accessible via the argument's public const members. In other words, equivalent values may be distinguishable.

```C++
struct Student {
    int score() const {
        return std::accumulate(cbegin(grades_), cend(grades_), 0, [](const auto& sum, const auto& pair) { return sum + pair.second; });
    }

    std::weak_ordering operator<=>(const Student& other) const {
        if (const auto res = this->score() <=> other.score(); res != 0) {
            return res;
        }
        return name_ <=> other.name_;
    }

    bool operator==(const Student&) const = default;

    std::string name_;
    std::multimap<std::string, int> grades_;
    int index_;
};

int main() {
    Student student1{.name_ = "Mateusz", .grades_ = {{"Math", 5},{"Bio", 4}}, .index_ = 456123};
    Student student2{.name_ = "Mateusz", .grades_ = {{"Math", 5},{"Eng", 4}}, .index_ = 123456};
    Student student3{.name_ = "Mateusz", .grades_ = {{"Math", 4},{"Phys", 3}}, .index_ = 123456};

    std::cout << "student1 > student2 ? " << (student1 > student2) << '\n';    // F 
    std::cout << "student1 < student2 ? " << (student1 < student2) << '\n';    // F 
    std::cout << "student1 != student2 ? " << (student1 != student2) << '\n';  // T (use operator == here) 
    std::cout << "student1 == student2 ? " << (student1 == student2) << '\n';  // F (use operator == here) 
    std::cout << "student1 > student3 ? " << (student1 > student3) << '\n';    // T (higher grades) 
    std::cout << "student1 < student3 ? " << (student1 < student3) << '\n';    // F 
}
```
<!-- .slide: style="font-size: 0.60em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## Implicit conversion

`std::strong_ordering` can be implicitly converted to `std::weak_ordering` and `std::weak_ordering` can be implicitly converted to `std::partial_ordering`.

___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## designated initializers

This is a small feature that you saw a few times in action during these lectures:

```C++
struct Student {
    std::string name_;
    std::multimap<std::string, int> grades_;
    int index_;
};

int main() {
    Student student1{.name_ = "Mateusz", .grades_ = {{"Math", 5},{"Bio", 4}}, .index_ = 456123};
    Student student2{.name_ = "Mateusz", .grades_ = {{"Math", 5},{"Eng", 4}}, .index_ = 123456};
    Student student3{.name_ = "Mateusz", .grades_ = {{"Math", 4},{"Phys", 3}}, .index_ = 123456};
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.85em" -->

___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

Every structure or class with public fields could now be initialized by using the name of a field. This makes code more readable and you don't need to switch a few times between headers and source code to check which field means what.

```C++
struct StreamInfo {
    std::string sourceAddress_;
    std::string destinationAddress_;
    uint16_t sourcePort_;
    uint16_t destinationPort_;
    uint16_t vlan_;
};

struct Streamer {
    Streamer(uint16_t sourcePort): sourcePort_(sourcePort) {}

    uint16_t getSourcePort() const { return sourcePort_; }
private:
    uint16_t sourcePort_;
};

int main() {
    std::map<std::string, std::string> ipTables;
    Streamer streamer(6523);
    ipTables.emplace("192.168.0.15", "192.168.0.35");
    ipTables.emplace("192.168.0.16", "192.168.0.42");

    StreamInfo info {
        .sourceAddress_ = "192.168.0.15",
        .destinationAddress_ = ipTables["192.168.0.15"],
        .sourcePort_ = streamer.getSourcePort(),
        .destinationPort_ = 9998,
        .vlan_ = [](){ return 123; }()
    };
}
```
<!-- .slide: style="font-size: 0.64em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## Atributes

Since C++20 we got 4 more atributes

* <!-- .element: class="fragment fade-in" --> <b>[[nodiscard("reason")]]</b> - encourages the compiler to issue a warning if the return value is discarded
* <!-- .element: class="fragment fade-in" --> <b>[[likely]]</b> and <b>[[unlikely]]</b> - indicates that the compiler should optimize for the case where a path of execution through a statement is more or less likely than any other path of execution
* <!-- .element: class="fragment fade-in" --> <b>[[no_unique_address]]</b> - indicates that a non-static data member need not have an address distinct from all other non-static data members of its class

___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## likely and unlikely

Everyone knows well this `if-else` statements:

```C++
if (!vec.empty()) { return vec.front(); }

if (divider != 0) {
    return num / divider;
} else {
    return std::nan("nan");
}

if (ptr) {
    return ptr->doSth();
}

if (name_ == other.name_) {
    return index < other.index_;
} else {
    return name_ < other.name_
}
```
* <!-- .element: class="fragment fade-in" --> <b>What is common for all of them?</b>
<!-- .slide: style="font-size: 0.94em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

Let's help compiler!

```C++
constexpr double pow(double x, int n) noexcept {
    if (n > 0) [[likely]] { return x * pow(x, n - 1); }
    else [[unlikely]] { return 1; }
}

constexpr double pow2(double x, int n) noexcept {
    if (n > 0) { return x * pow(x, n - 1); }
    else { return 1; }
}

int main() {
    auto benchmark = [](auto fun) {
        const auto start = std::chrono::high_resolution_clock::now();
        fun();
        const auto diff = std::chrono::high_resolution_clock::now() - start;
        std::cout << "Time: " << std::fixed << std::setprecision(6) << diff.count() << " ns\n";
    };

    std::vector<double> vec(1'000'000);
    std::iota(begin(vec), end(vec), 1);
    benchmark([&]() { for (auto el : vec) { pow(el, 13); } });
    benchmark([&]() { for (auto el : vec) { pow2(el, 13); } });
    // Time: 59839100 ns
    // Time: 79786800 ns
}
```
<!-- .slide: style="font-size: 0.76em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

There is more!

```C++
int Nwd(int a, int b) {
    while (b != 0) [[likely]] { a = std::exchange(b, a % b); }
    return a;
}

int Nwd2(int a, int b) {
    while (b != 0) { a = std::exchange(b, a % b); }
    return a;
}

int main() {
    auto benchmark = [](auto fun) {
        const auto start = std::chrono::high_resolution_clock::now();
        fun();
        const auto diff = std::chrono::high_resolution_clock::now() - start;
        std::cout << "Time: " << std::fixed << std::setprecision(6) << diff.count() << " ns\n";
    };

    std::vector<double> vec(1'000'000);
    std::iota(begin(vec), end(vec), 1);
    benchmark([&](){ for (auto el : vec) { Nwd(1'000'000, el); } });
    benchmark([&](){ for (auto el : vec) { Nwd2(1'000'000, el); } });
    // Time: 140909100 ns
    // Time: 182572100 ns
}
```
<!-- .slide: style="font-size: 0.76em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## Ok ok, but what happens when I already use optimization flag?

```C++
int main() {
    auto benchmark = [](auto fun) {
        const auto start = std::chrono::high_resolution_clock::now();
        fun();
        const auto diff = std::chrono::high_resolution_clock::now() - start;
        std::cout << "Time: " << std::fixed << std::setprecision(6) << diff.count() << " ns\n";
    };

    std::vector<double> vec(1'000'000);
    std::iota(begin(vec), end(vec), 1);
    int res = 0;
    benchmark([&](){ for (auto el : vec) { res += Nwd(1'000'000, el); } });  // Time: 88765100 ns
    benchmark([&](){ for (auto el : vec) { res += Nwd2(1'000'000, el); } }); // Time: 82797600 ns
    benchmark([&]() { for (auto el : vec) { res += pow(el, 13); } });        // Time: 6002300 ns
    benchmark([&]() { for (auto el : vec) { res += pow2(el, 13); } });       // Time: 8012500 ns

    return res;
}
```

<b>Wait what?!</b>. When we use <b>-O3</b> optimization flag we got worse output for <b>[[likely]]</b>. It depends on various things, sometimes code run faster sometimes not, but generally, you can't charm the compiler with optimization, but sometimes you can help :)
<!-- .slide: style="font-size: 0.76em" -->
<!-- .element: class="fragment fade-in" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

Use it when it is worth it, and the compiler could have a problem with manual optimization. For instance in 99.99% during response validation, an error occurs when there is no `result` filed, other cases happen mainly when someone implements wrong behavior and this is eliminated during tests. Ofc you still can always write more predictable if statement at the beginning :) And this is even better option in my opinion.

```C++
bool validate(const std::string& str) {
    constexpr char kResult[] = "result:";

    if (str.empty()) [[unlikely]] {
        return false;
    } else if (str.size() > 30) [[unlikely]] {
        return false;
    } else if (str.front() != '{') [[unlikely]] {
        return false;
    } else if (str.back() != '}') [[unlikely]] {
        return false;
    } else if (std::all_of(std::cbegin(str), std::cend(str), [](const char c) { return !std::isalnum(c); })) [[unlikely]] {
        return false;
    } else if (std::search(std::cbegin(str), std::cend(str), std::cbegin(kResult), std::cend(kResult)) ==
               std::cend(str)) [[likely]] {
        return false;
    }

    return true;
}

bool validate2(const std::string& str) {
    constexpr char kResult[] = "result:";

    if (str.empty()) {
        return false;
    } else if (str.size() > 30) {
        return false;
    } else if (str.front() != '{') {
        return false;
    } else if (str.back() != '}') {
        return false;
    } else if (std::all_of(std::cbegin(str), std::cend(str), [](const char c) { return !std::isalnum(c); })) {
        return false;
    } else if (std::search(std::cbegin(str), std::cend(str), std::cbegin(kResult), std::cend(kResult)) ==
               std::cend(str)) {
        return false;
    }

    return true;
}

int main() {
    auto benchmark = [](auto fun) {
        const auto start = std::chrono::high_resolution_clock::now();
        fun();
        const auto diff = std::chrono::high_resolution_clock::now() - start;
        std::cout << "Time: " << std::fixed << std::setprecision(6) << diff.count() << " ns\n";
    };

    int wrong = 0;
    std::vector<std::string> vec(1'000'000, "{result:12345}");
    benchmark([&]() {
        wrong += std::count_if(std::cbegin(vec), std::cend(vec), [](const auto& str) { return validate(str); });
    });
    benchmark([&]() {
        wrong += std::count_if(std::cbegin(vec), std::cend(vec), [](const auto& str) { return validate2(str); });
    });
    // Time: 293222100 ns
    // Time: 376011000 ns
    // 
    // With 03
    // Time: 14437300 ns
    // Time: 21943400 ns

    return wrong;
}
```
<!-- .slide: style="font-size: 0.67em" -->
<!-- .element: class="fragment fade-in" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## no_unique_address 

Allows this data member to be overlapped with other non-static data members or base class subobjects of its class. Generally, we can use it when we have an empty filed in the structure, and we don't want to lost 1 byte to store it.

```C++
struct Empty {};

struct Filed {
    int val_;
    double val2_;
    Empty empty_;
};

struct Filed2 {
    int val_;
    double val2_;
    [[no_unique_address]] Empty empty_;
};

int main() {
    static_assert(sizeof(Empty) >= 1);
    std::cout << "sizeof(Filed): " << sizeof(Filed) << '\n';  // 24
    std::cout << "sizeof(Filed): " << sizeof(Filed2) << '\n'; // 16
}
```
<!-- .slide: style="font-size: 0.80em" -->
<!-- .element: class="fragment fade-in" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## pack-expansion in lmabdas

Since C++20 we can easily move all arguments to lambda. Before C++20 we can do this only for one object, but now it works for packages also.

```C++
auto postponeTask(auto&& fun, auto&&... args) {
    return [f = std::move(fun), ... pack = std::move(args)]() {
        return f(pack...);
    };
}

int main() {
    auto task = postponeTask([](const std::string& str, int num) {
        std::cout << str << " | " << num << '\n';
    }, std::string("Ala ma kota"), 42);

    task();
}
```
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

If you don't have C++20 (but you have C++17) you can still use the trick with the `std::tuple` with `std::apply` method.

```C++
template <typename Fun, typename... Args>
auto postponeTask(Fun fun, Args... args) {
    return [fun = std::move(fun), tup = std::make_tuple(std::move(args)...)]() -> decltype(auto) {
        return std::apply([fun = std::move(fun)](auto const&... args) -> decltype(auto) {
            return fun(args...);
        }, tup);
    };
}
int main() {
    auto task = postponeTask([](const std::string& str, int num) {
        std::cout << str << " | " << num << '\n';
    }, std::string("Ala ma kota"), 42);

    task();
}
```
<!-- .slide: style="font-size: 0.85em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## template syntax for lambdas

Ok, but what if I want to perfect forward arguments, instead of moving them? Since C++20 you can use template syntax!

```C++
int main() {
    auto benchmark = []<typename... Args>(auto&& fun, Args... args) {
        const auto now = std::chrono::system_clock::now();
        const auto res = std::move(fun)(std::forward<Args>(args)...);
        const auto then = std::chrono::system_clock::now();
        std::cout << "res: " << res << " | time: " << (then - now).count() << " ns\n";
    };

    benchmark([](int count, int init) -> long long {
        std::vector<int> vec(count);
        std::iota(begin(vec), end(vec), init);
        return std::accumulate(begin(vec), end(vec), 0);
    }, 1'000'000, 50);
}
```
<!-- .slide: style="font-size: 0.90em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## uniform erasure

Ok let's do sth easier! How many times have you written sth like this :)?

```C++
std::vector<int> vec {1,2,3,4,5,6};
vec.erase(std::remove_if(begin(vec), end(vec), [](auto num){ return num & 1; }), vec.end());
```
<!-- .element: class="fragment fade-in" -->

`std::remove` only prepares a vector to actually remove, but in the end, we need to erasure these values. Yes, this is why a lot of ppl hate C++, always complications. For instance we can write sth like this:
<!-- .element: class="fragment fade-in" -->

```C++
std::map<std::string, int> map {{"One", 1}, {"Two", 2}, {"Three", 3}};
map.erase("One");

std::list<std::string> list {"Ala", "ma", "kota"};
list.remove("Ala");
```
<!-- .element: class="fragment fade-in" -->

In the case of a list, there is a member function `remove`, which actually removes an element! But for the map, we have only `erase`, which also takes a key as a value and removes an element. 3 containers and 3 different behavior. Definitely, newcomers won't like this. The funniest part is that list has `remove_if` method, but the map doesn't have `erase_if` ;)
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.82em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

Since C++20 erasing elements is finally unified! We have two options, `erase` or `erase_if`. Unfortunately, in C++ there is always an exception to the rule. `std::map` and `std::set` (and their hash versions) don't have `std::erase` overload, because they already have specialized members functions.

```C++
    std::vector<int> vec {1,2,3,4,5,6};
    std::erase(vec, 4);
    std::erase_if(vec, [](auto num){ return num & 1; });
    
    std::map<std::string, int> map {{"One", 1}, {"Two", 2}, {"Three", 3}};
    map.erase("One"); // There is no std::erase() for map :/
    std::erase_if(map, [](const auto& pair){ return pair.second == 2; }); // But there is std::erase_if
    
    std::list<std::string> list {"Ala", "ma", "kota"};
    std::erase(list, "ma");
    std::erase_if(list, [](const auto& str){ return str.length() == 3; });

    std::unordered_set<int> set{1,2,3,4,5,6};
    set.erase(4);
    std::erase_if(set, [](auto num){ return num & 1; });
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.81em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## source_loaction

Since C++20 we got a nice functionality to perform easy and efficient logging.

```C++
void log(const std::string_view message,
         const std::source_location location = 
               std::source_location::current())
{
    std::cout << "file: "
              << location.file_name() << "("
              << location.line() << ":"
              << location.column() << ") `"
              << location.function_name() << "`: "
              << message << '\n';
}
 
template <typename T> void fun(T x)
{
    log(x);
}
 
int main(int, char*[])
{
    log("Hello world!");
    fun("Hello C++20!");
}
```

```bash
file: prog.cc(24:8) `int main(int, char**)`: Hello world!
file: prog.cc(19:8) `void fun(T) [with T = const char*]`: Hello C++20!
```
<!-- .slide: style="font-size: 0.75em" -->
<!-- .element: class="fragment fade-in" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

It's easy to rebuild a little this solution and create own logger:

```C++
enum LogType {INF, WRN, ERR};

struct Logger {
    Logger(LogType logType, std::source_location location = std::source_location::current()): 
        logType_{logType},
        location_{location} {}

    Logger& operator<<(std::string_view message) {
        const auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
        std::ostringstream os;
        os << "[" << toString(logType_) << "]"
           << "(" << std::put_time(std::localtime(&time), "%Y-%m-%d %X") << "): "
           << location_.file_name() << "("
           << location_.line() << ":"
           << location_.column() << ") `"
           << location_.function_name() << "`: "
           << message << '\n';
        file_ << os.str() << std::flush;

        return *this;
    }

private:
    std::string_view toString(LogType logType) {
        switch (logType) {
        case INF: return "INFO";
        case WRN: return "WARNING";
        case ERR: return "ERROR";
        default: return "UNKNOWN!";
        }
    }

    LogType logType_;
    std::source_location location_;
    static std::ofstream file_;
};

std::ofstream Logger::file_("log.txt");
```
<!-- .slide: style="font-size: 0.75em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

Ok now is time to log sth 

```C++
int main() {
    Logger(INF) << "Hello!" << "And Hi" << "And Dzien dobry!";
    Logger(WRN) << "Ojej!";
    Logger(ERR) << "Critical!!!" << "UPS!" << "Bad bad!";
}
```

And in file `log.txt` we got:
<!-- .element: class="fragment fade-in" -->

```C++
[INFO](2022-05-22 14:24:47): prog.cc(55:15) `int main()`: Hello!
[INFO](2022-05-22 14:24:47): prog.cc(55:15) `int main()`: And Hi
[INFO](2022-05-22 14:24:47): prog.cc(55:15) `int main()`: And Dzien dobry!
[WARNING](2022-05-22 14:24:47): prog.cc(56:15) `int main()`: Ojej!
[ERROR](2022-05-22 14:24:47): prog.cc(57:15) `int main()`: Critical!!!
[ERROR](2022-05-22 14:24:47): prog.cc(57:15) `int main()`: UPS!
[ERROR](2022-05-22 14:24:47): prog.cc(57:15) `int main()`: Bad bad!
```
<!-- .slide: style="font-size: 0.86em" -->
<!-- .element: class="fragment fade-in" -->

___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

# bit operations

There is a new header `<bit>` which allows performing many valuable operations on bits. All functions are declared as constexpr, so there is a big chance that everything will be evaluated at compile time! Finally, you don't need to write an ugly macro. Let's start with the most important one.

`std::endian` indicates the endianness of all scalar types:

- <!-- .element: class="fragment fade-in" --> If all scalar types are little-endian, std::endian::native equals std::endian::little
- <!-- .element: class="fragment fade-in" --> If all scalar types are big-endian, std::endian::native equals std::endian::big

Corner case platforms are also supported:
<!-- .element: class="fragment fade-in" -->

- <!-- .element: class="fragment fade-in" --> If all scalar types have sizeof equal to 1, endianness does not matter and all three values, std::endian::little, std::endian::big, and std::endian::native are the same.
- <!-- .element: class="fragment fade-in" --> If the platform uses mixed endian, std::endian::native equals neither std::endian::big nor std::endian::little.

```C++
int main() {
 
    if constexpr (std::endian::native == std::endian::big)
        std::cout << "big-endian\n";
    else if constexpr (std::endian::native == std::endian::little)
        std::cout << "little-endian\n";
    else std::cout << "mixed-endian\n";
    // Output: little-endian
}
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.70em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

For me very usefull is also `popcount`, and all `countX_Y` function, where`X` could be `l` - left, `r` - right, and `Y` could be `zero` or `one`:

```C++
int main() {
    // counts the number of 1 bits in an unsigned integer
    std::cout << std::popcount(0b1010101010101u) << '\n'; // 7

    // counts the number of consecutive 1 bits, starting from the most significant bit
    std::cout << std::countl_one(std::numeric_limits<uint8_t>::max()) << '\n'; // 8 

    // counts the number of consecutive 0 bits, starting from the most significant bit
    std::cout << std::countl_zero(0b111000011111u) << '\n'; // 20 because this is uint32_t

    // counts the number of consecutive 1 bits, starting from the least significant bit
    std::cout << std::countr_one(0b111000011111u) << '\n'; // 5

    // counts the number of consecutive 0 bits, starting from the least significant bit
    std::cout << std::countr_zero(0b111000011100u) << '\n'; // 2
}
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.90em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

Sometimes in the algorithm, we need to know the closest power of 2 for a given number.

```C++
int main() {
    for (uint8_t i = 0 ; i < 16 ; ++i) {
        std::cout << "num: " << std::bitset<sizeof(i) << 3>(i)
                  << " | bit_width: " << +std::bit_width(i) 
                  << " | power of 2: " << std::has_single_bit(i)
                  << " | floor: " << +std::bit_floor(i)
                  << " | ceil: " << +std::bit_ceil(i) << '\n';
    }
}
```
```bash
num: 00000000 | bit_width: 0 | power of 2: 0 | floor: 0 | ceil: 1
num: 00000001 | bit_width: 1 | power of 2: 1 | floor: 1 | ceil: 1
num: 00000010 | bit_width: 2 | power of 2: 1 | floor: 2 | ceil: 2
num: 00000011 | bit_width: 2 | power of 2: 0 | floor: 2 | ceil: 4
num: 00000100 | bit_width: 3 | power of 2: 1 | floor: 4 | ceil: 4
num: 00000101 | bit_width: 3 | power of 2: 0 | floor: 4 | ceil: 8
num: 00000110 | bit_width: 3 | power of 2: 0 | floor: 4 | ceil: 8
num: 00000111 | bit_width: 3 | power of 2: 0 | floor: 4 | ceil: 8
num: 00001000 | bit_width: 4 | power of 2: 1 | floor: 8 | ceil: 8
num: 00001001 | bit_width: 4 | power of 2: 0 | floor: 8 | ceil: 16
num: 00001010 | bit_width: 4 | power of 2: 0 | floor: 8 | ceil: 16
num: 00001011 | bit_width: 4 | power of 2: 0 | floor: 8 | ceil: 16
num: 00001100 | bit_width: 4 | power of 2: 0 | floor: 8 | ceil: 16
num: 00001101 | bit_width: 4 | power of 2: 0 | floor: 8 | ceil: 16
num: 00001110 | bit_width: 4 | power of 2: 0 | floor: 8 | ceil: 16
num: 00001111 | bit_width: 4 | power of 2: 0 | floor: 8 | ceil: 16
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.80em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

There is also a rotation `left` /` right`. Standard `c ++ 23` introduced also` byteswap` to convert variables from little endian to big endian and vice versa.

```C++
uint16_t num = 0b1111001100111001;
std::cout << "num: " << std::bitset<16>(num) << "\n\n";
for (uint8_t i = 0 ; i < 16 ; ++i) {
    std::cout << "rotr: " << std::bitset<16>(std::rotr(num, i))
                << " | rotl: " << std::bitset<16>(std::rotl(num, i))
                << '\n';
}
```

```bash
num: 1111001100111001

rotr: 1111001100111001 | rotl: 1111001100111001
rotr: 1111100110011100 | rotl: 1110011001110011
rotr: 0111110011001110 | rotl: 1100110011100111
rotr: 0011111001100111 | rotl: 1001100111001111
rotr: 1001111100110011 | rotl: 0011001110011111
rotr: 1100111110011001 | rotl: 0110011100111110
rotr: 1110011111001100 | rotl: 1100111001111100
rotr: 0111001111100110 | rotl: 1001110011111001
rotr: 0011100111110011 | rotl: 0011100111110011
rotr: 1001110011111001 | rotl: 0111001111100110
rotr: 1100111001111100 | rotl: 1110011111001100
rotr: 0110011100111110 | rotl: 1100111110011001
rotr: 0011001110011111 | rotl: 1001111100110011
rotr: 1001100111001111 | rotl: 0011111001100111
rotr: 1100110011100111 | rotl: 0111110011001110
rotr: 1110011001110011 | rotl: 1111100110011100
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.75em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## format your string like in <code>printf</code>

The main problem with `std::cout` is a problem with easy formatting (I know streams are also inefficient, but this is not a point right now). For instance:

```C++
int main() {
    for (uint8_t i = 0 ; i < 16 ; ++i) {
        std::cout << "num: " << std::bitset<sizeof(i) << 3>(i)
                  << " | bit_width: " << +std::bit_width(i) 
                  << " | power of 2: " << std::has_single_bit(i)
                  << " | floor: " << +std::bit_floor(i)
                  << " | ceil: " << +std::bit_ceil(i) << '\n';
    }
}
```
<!-- .element: class="fragment fade-in" -->
With `<format>` library now we can write:
<!-- .element: class="fragment fade-in" -->

```C++
for (uint8_t i = 0; i < 16; ++i) {
    std::cout << std::format("num: {} | bit_width: {} | power of 2: {} | floor: {} | ceil {}\n",
                            std::bitset<sizeof(i) << 3>(i).to_string(),
                            std::bit_width(i),
                            std::has_single_bit(i),
                            std::bit_floor(i),
                            std::bit_ceil(i));
}
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.75em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

On day `25.05.2022` the newest `gcc 13` didn't support the library `<format>`. Fortunately `clang 15` already supports it! `<Format>` library is very powerful, we can easily create any format we want and pass any values we need:

```C++
void raw_write_to_log(std::string_view users_fmt, std::format_args&& args) {
    constinit static int line{};
    std::clog << std::format("{:04} : ", line++) << std::vformat(users_fmt, args) << '\n';
}
 
template <typename... Args>
constexpr void log(Args&&... args) {
    // Generate formatting string "{} "...
    std::array<char, sizeof...(Args) * 3 + 1> braces{};
    constexpr const char c[] = "{} ";
    for (auto i{0u}; i != braces.size() - 1; ++i) {
        braces[i] = c[i % 3];
    }
    braces.back() = '\0';
 
    raw_write_to_log(braces.data(), std::make_format_args(std::forward<Args>(args)...));
}

int main()
{
    std::string str{"Printable"};
    log("You", "Can", "Pass", "Any", "Number", "Of", "Arguments");
    log("Everything", "Which", "Can", "Be", str);
    log(1, 4.5, 1234);
}
```
<!-- .element: class="fragment fade-in" -->
```bash
0000 : You Can Pass Any Number Of Arguments 
0001 : Everything Which Can Be Printable 
0002 : 1 4.5 1234 
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.68em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

## Limitations

We need to wait to specify how we should specify custom object formatting. Currently on cppreference we can see an example, but looking very ugly and don't compile on `clang 15`.

```C++
#include <format>
#include <iostream>
 
// A wrapper for type T
template<class T>
struct Box {
    T value;
};
 
// The wrapper Box<T> can be formatted using the format specification of the wrapped value
template<class T, class CharT>
struct std::formatter<Box<T>, CharT> : std::formatter<T, CharT> {
    // parse() is inherited from the base class
 
    // Define format() by calling the base class implementation with the wrapped value
    template<class FormatContext>
    auto format(Box<T> t, FormatContext& fc) const {
        return std::formatter<T, CharT>::format(t.value, fc);
    }
};
 
int main() {
    Box<int> v = { 42 };
    std::cout << std::format("{:#x}", v);
}
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.72em" -->
___
<!-- .slide: data-background="#ccc" --><!-- .slide: data-background="#ccc" -->

But to make you more interested in this library check out more possibilities:

```C++
int main()
{
    std::string buffer;
    
    std::format_to(
        std::back_inserter(buffer),
        "Hello, C++{}!\n", // formater
        "20",   // args
        "More args, make no error :)");

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

```bash
Hello, C++20!
```
<!-- .element: class="fragment fade-in" -->
<!-- .slide: style="font-size: 0.82em" -->
