## constexpr - one of the most undervalued feature in modern C++ (1)

* <!-- .element: class="fragment fade-in" --> <code>constexpr</code> was introduced in C++11
    * <!-- .element: class="fragment fade-in" --> constexpr values are know during compilation process
    * <!-- .element: class="fragment fade-in" --> Function also could be constexpr with some restriction:
        * <!-- .element: class="fragment fade-in" --> they may only have exactly one statement and this statement had to be a return statement
        * <!-- .element: class="fragment fade-in" --> not allowed to have any side effects, like if-else
        * <!-- .element: class="fragment fade-in" --> not allowed to have exception and try-catch block
        * <!-- .element: class="fragment fade-in" --> can use ternary operator
        * <!-- .element: class="fragment fade-in" --> Usually wrote recurent rather then iterative functions
        * <!-- .element: class="fragment fade-in" --> Functions behave like normal functions (not solved during compilation) when working with non-constexpr arguments
    * <!-- .element: class="fragment fade-in" --> Class/ struct could have constexpr C'tor and member functions
* <!-- .element: class="fragment fade-in" --> In C++14 introduced:
    * <!-- .element: class="fragment fade-in" --> <b>Less restrictions for functions</b>:
        * <!-- .element: class="fragment fade-in" --> more then one return
        * <!-- .element: class="fragment fade-in" --> can use if-else
___

###  constexpr - one of the most undervalued feature in modern C++ (2)

* <!-- .element: class="fragment fade-in" --> In C++17 introduced:
    * <!-- .element: class="fragment fade-in" --> constexpr class string_view
    * <!-- .element: class="fragment fade-in" --> <b>constexpr std::array</b>
    * <!-- .element: class="fragment fade-in" --> constexpr iterator for array and std::begin, std::end functions
    * <!-- .element: class="fragment fade-in" --> <b>constexpr lambda</b>
* <!-- .element: class="fragment fade-in" --> In C++20 introduced:
    * <!-- .element: class="fragment fade-in" --> <b>constexpr STL algorithms</b>
    * <!-- .element: class="fragment fade-in" --> <b>constexpr std::vector and std::string</b> and their iterators. (not supported by clang and gcc. Surprisely its supported by MSVC STL)
    * <!-- .element: class="fragment fade-in" --> Allow to use try-catch in constexpr functions
    * <!-- .element: class="fragment fade-in" --> Allow to allocate and deallocate values on heap, but need to free them before exit function
    * <!-- .element: class="fragment fade-in" --> Allow to create virtual functions
    * <!-- .element: class="fragment fade-in" --> Allow to use asm code block
___

## C++11 constexpr function

```C++
#include <cstddef>

constexpr bool isLower(char c) {
    return c >= 'a' && c <= 'z';
}

template <typename T, size_t N>
constexpr size_t countLower(const T (&str)[N], size_t current, size_t counter) {
    return current == N
               ? counter
           : isLower(str[current])
               ? countLower(str, current + 1, counter + 1)
               : countLower(str, current + 1, counter);
}

int main() {
    static_assert(9 == countLower("Ala has a cat", 0, 0));
}
```
<!-- .element: class="fragment fade-in" --> 

```Bash
xor    eax,eax
ret    
nop    WORD PTR cs:[rax+rax*1+0x0]
nop    DWORD PTR [rax]
```
<!-- .element: class="fragment fade-in" --> 
<style>
div {text-align: center;}
</style>
<div>check on <a href="https://godbolt.org/">https://godbolt.org/</a></div>
<!-- .element: class="fragment fade-in" --> 
<!-- .slide: style="font-size: 0.75em" -->
___

## C++14 constexpr function

```C++
constexpr bool isLower(char c) {
    return c >= 'a' && c <= 'z';
}

template <typename T, size_t N>
constexpr size_t countLower(const T (&str)[N]) {
    size_t counter = 0;
    for (auto c : str) {
        if (isLower(c)) {
            ++counter;
        }
    }

    return counter;
}

int main() {
    static_assert(9 == countLower("Ala has a cat"));
}
```
<!-- .element: class="fragment fade-in" --> 

```Bash
xor    eax,eax
ret    
nop    WORD PTR cs:[rax+rax*1+0x0]
nop    DWORD PTR [rax]
```
<!-- .element: class="fragment fade-in" --> 
<style>
div {text-align: center;}
</style>
<div>check on <a href="https://godbolt.org/">https://godbolt.org/</a></div>
<!-- .element: class="fragment fade-in" --> 
<!-- .slide: style="font-size: 0.75em" -->
___

## C++17 constexpr function (1)

```C++
template <typename T, size_t N>
constexpr size_t countLower(const T (&str)[N]) {
    constexpr auto isLower = [](char c) { return c >= 'a' && c <= 'z'; };
    size_t counter = 0;

    for (auto c : str) {
        if (isLower(c)) {
            ++counter;
        }
    }

    return counter;
}

int main() {
    static_assert(9 == countLower("Ala has a cat"));
}
```
<!-- .element: class="fragment fade-in" --> 

```Bash
xor    eax,eax
ret    
nop    WORD PTR cs:[rax+rax*1+0x0]
nop    DWORD PTR [rax]
```
<!-- .element: class="fragment fade-in" --> 
<style>
div {text-align: center;}
</style>
<div>check on <a href="https://godbolt.org/">https://godbolt.org/</a></div>
<!-- .element: class="fragment fade-in" --> 
<!-- .slide: style="font-size: 0.75em" -->
___

## C++17 constexpr function (2)

```C++
constexpr size_t countLower(const std::string_view& str) {
    constexpr auto isLower = [](char c) { return c >= 'a' && c <= 'z'; };
    size_t counter = 0;

    for (size_t i = 0 ; i < str.size() ; ++i) {
        if (isLower(str[i])) {
            ++counter;
        }
    }

    return counter;
}

int main() {
    static_assert(9 == countLower("Ala has a cat"));
}
```
<!-- .element: class="fragment fade-in" --> 

```Bash
xor    eax,eax
ret    
cs nop WORD PTR [rax+rax*1+0x0]
nop    DWORD PTR [rax]
```
<!-- .element: class="fragment fade-in" --> 
<style>
div {text-align: center;}
</style>
<div>check on <a href="https://godbolt.org/">https://godbolt.org/</a></div>
<!-- .element: class="fragment fade-in" --> 
<!-- .slide: style="font-size: 0.75em" -->
___

## C++20 constexpr function
```C++
constexpr size_t countLower(const std::string& str) {
    constexpr auto isLower = [](char c) { return c >= 'a' && c <= 'z'; };
    size_t counter = 0;

    for (size_t i = 0 ; i < str.size() ; ++i) {
        if (isLower(str[i])) {
            ++counter;
        }
    }

    return counter;
}

int main() {
    static_assert(9 == countLower(std::string("Ala has a cat")));
}
```
<style>
div {text-align: center;}
</style>
<div>check on <a href="https://en.cppreference.com/w/cpp/compiler_support">https://en.cppreference.com/w/cpp/compiler_support</a></div>
<!-- .element: class="fragment fade-in" --> 
<!-- .slide: style="font-size: 0.75em" -->
___

## C++20 constexpr function - algorithms 

```C++
constexpr size_t countLower(const std::string& str) {
    constexpr auto isLower = [](char c) { return c >= 'a' && c <= 'z'; };
    return std::count_if(cbegin(str), cend(str), isLower);
}

int main() {
    static_assert(9 == countLower(std::string("Ala has a cat")));
}
```
<style>
div {text-align: center;}
</style>
<div>check on <a href="https://en.cppreference.com/w/cpp/compiler_support">https://en.cppreference.com/w/cpp/compiler_support</a></div>
<!-- .element: class="fragment fade-in" --> 
<!-- .slide: style="font-size: 0.75em" -->
___

## C++20 constexpr - allocation on heap (1)

```C++
template <typename T, size_t N>
constexpr std::array<T, N> generatePseudoRandom(int from, int to) {
    std::array<T, N> arr;
    const int seed = ((N << 1) ^ (from << to) ^ to) ^ ((from + to) ^ (N << 3));
    const size_t size = to - from;
    auto tmp = new int[size];
    std::iota(tmp, tmp + size, from);

    for (int i = 0; i < N; ++i) {
        arr[i] = tmp[(seed ^ i) % size];
    }

    delete[] tmp;
    return arr;
}

int main() {
    static_assert(generatePseudoRandom<int, 10>(10, 20).size() == 10);
}
```
<!-- .element: class="fragment fade-in" --> 

```C++
Will print: 18 19 16 17 14 15 12 13 10 11
```
<!-- .element: class="fragment fade-in" --> 

```Bash
xor    eax,eax
ret    
cs nop WORD PTR [rax+rax*1+0x0]
nop    DWORD PTR [rax]
```
<!-- .element: class="fragment fade-in" --> 
<style>
div {text-align: center;}
</style>
<div>check on <a href="https://godbolt.org/">https://godbolt.org/</a></div>
<!-- .element: class="fragment fade-in" --> 
<!-- .slide: style="font-size: 0.68em" -->
___

## C++20 constexpr - allocation on heap (1)

If we forget to add <code>delete[]</code>, compiler will detect it!

```C++
template <typename T, size_t N>
constexpr std::array<T, N> generatePseudoRandom(int from, int to) {
    std::array<T, N> arr;
    const int seed = ((N << 1) ^ (from << to) ^ to) ^ ((from + to) ^ (N << 3));
    const size_t size = to - from;
    auto tmp = new int[size];
    std::iota(tmp, tmp + size, from);

    for (int i = 0; i < N; ++i) {
        arr[i] = tmp[(seed ^ i) % size];
    }

    //delete[] tmp;
    return arr;
}

int main() {
    static_assert(generatePseudoRandom<int, 10>(10, 20).size() == 10);
}
```
<!-- .element: class="fragment fade-in" --> 

```C++
<source>: In function 'int main()':
<source>:22:64: error: non-constant condition for static assertion
   22 |     static_assert(generatePseudoRandom<int, 10>(10, 20).size() == 10);
      |                   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
<source>:10:16: error: '(generatePseudoRandom<int, 10>(10, 20).std::array<int, 10>::size() == 10)' is not a constant expression because allocated storage has not been deallocated
   10 |     auto tmp = new int[size];
      |                ^~~~~~~~~~~~~
Execution build compiler returned: 1
```
<!-- .element: class="fragment fade-in" --> 
<!-- .slide: style="font-size: 0.62em" -->
___

### contexpr-if (1)

* <!-- .element: class="fragment fade-in" --> Who uses SFINAE?
* <!-- .element: class="fragment fade-in" --> Who likes SFINAE?

```C++
namespace {
constexpr double epsilon = 0.000001;
}

template <class T> 
constexpr std::enable_if_t<std::is_floating_point_v<T>, bool> 
equal(T lhs, T rhs) {
   return std::abs(lhs - rhs) < epsilon;
}

template <class T>
constexpr std::enable_if_t<!std::is_floating_point_v<T>, bool> 
equal(T lhs, T rhs) {
   return lhs == rhs;
}

int main() {
    static_assert(equal(10, 10) == true);
    static_assert(equal(10.123f, 10.123f) == true);
    static_assert(equal(10.45678, 10.45678) == true);
}
```
<!-- .element: class="fragment fade-in" --> 

```C++
xor    eax,eax
ret    
cs nop WORD PTR [rax+rax*1+0x0]
nop    DWORD PTR [rax]
```
<!-- .element: class="fragment fade-in" --> 
<!-- .slide: style="font-size: 0.62em" -->
___

### contexpr-if (2)

```C++
template <typename T>
constexpr bool equal(T lhs, T rhs) {
    constexpr double epsilon = 0.000001;

    if constexpr (std::is_floating_point_v<T>) {
        return std::abs(lhs - rhs) < epsilon;
    } else {
        return lhs == rhs;
    }
}

int main() {
    static_assert(equal(10, 10) == true);
    static_assert(equal(10.123f, 10.123f) == true);
    static_assert(equal(10.45678, 10.45678) == true);
}
```
<!-- .element: class="fragment fade-in" --> 

```C++
xor    eax,eax
ret    
cs nop WORD PTR [rax+rax*1+0x0]
nop    DWORD PTR [rax]
```
<!-- .element: class="fragment fade-in" --> 
<!-- .slide: style="font-size: 0.62em" -->
___

### C++20 concept

```C++
template <typename T>
requires std::is_floating_point_v<T>
constexpr bool equal(T lhs, T rhs) {
    constexpr double epsilon = 0.000001;

    return std::abs(lhs - rhs) < epsilon;
}

// Work only, when both types are equal!
constexpr bool equal(auto lhs, auto rhs) {
    return lhs == rhs;
}

int main() {
    static_assert(equal(10, 10) == true);
    static_assert(equal(10.123f, 10.123f) == true);
    static_assert(equal(10.45678, 10.45678) == true);
}
```
<!-- .element: class="fragment fade-in" --> 

```C++
xor    eax,eax
ret    
cs nop WORD PTR [rax+rax*1+0x0]
nop    DWORD PTR [rax]
```
<!-- .element: class="fragment fade-in" --> 
<!-- .slide: style="font-size: 0.62em" -->
