Upgrade to Pro — share decks privately, control downloads, hide ads and more …

42 silly ways to say "Hello" in modern C++ (Sep 2018)

Olve Maudal
September 25, 2018

42 silly ways to say "Hello" in modern C++ (Sep 2018)

The title says "silly", but this is really a serious attempt to compress essential stuff from a 2 day course on modern C++ into a brief presentation.

Olve Maudal

September 25, 2018
Tweet

More Decks by Olve Maudal

Other Decks in Programming

Transcript

  1. 42 silly ways to say "Hello" in modern C++ (September 2018)
    Olve Maudal, Ministry of Silly C++ Code Snippets
    1
    a 20 minute presentation
    September 2018

    View Slide

  2. 2
    This is an attempt to stuff the content of a
    two day course into a 20 minute presentation.
    There are 436 slides. Fasten your
    seatbelts. Enjoy the ride!

    View Slide

  3. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    3

    View Slide

  4. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    4
    Consider this C++ program demonstrating the
    use of iterators.

    View Slide

  5. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    5
    We have a sequence of characters.

    View Slide

  6. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    6
    We compute the address to the beginning
    and to the end of the sequence.

    View Slide

  7. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    7
    We pass an iterator pair to our print function.

    View Slide

  8. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    8

    View Slide

  9. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    9

    View Slide

  10. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    10

    View Slide

  11. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    11

    View Slide

  12. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    12
    We iterate through every address from begin
    to, but not including, the end.

    View Slide

  13. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    13

    View Slide

  14. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    14
    For each step, the iterator is dereferenced
    and the value is used as an argument to
    std::putchar

    View Slide

  15. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    15

    View Slide

  16. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    16
    The output of this program is... of course...

    View Slide

  17. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    17
    Hello

    View Slide

  18. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    18
    Hello
    ..
    1

    View Slide

  19. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    19
    Hello
    One down, 41 to go.
    ..
    1
    iterators

    View Slide

  20. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    20

    View Slide

  21. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    21
    In the C++ standard library, there are helper
    functions to find the begin and end of a
    sequence.

    View Slide

  22. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = &seq[0];
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    22

    View Slide

  23. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = std::cbegin(seq);
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    23

    View Slide

  24. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = std::cbegin(seq);
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    24

    View Slide

  25. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = std::cbegin(seq);
    const char * end = &seq[std::size(seq)];
    print(begin, end);
    }
    25

    View Slide

  26. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = std::cbegin(seq);
    const char * end = std::cend(seq);
    print(begin, end);
    }
    26

    View Slide

  27. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = std::cbegin(seq);
    const char * end = std::cend(seq);
    print(begin, end);
    }
    27

    View Slide

  28. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = std::cbegin(seq);
    const char * end = std::cend(seq);
    print(begin, end);
    }
    28
    Hello
    ..
    2
    std::cbegin() and std::cend()

    View Slide

  29. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = std::cbegin(seq);
    const char * end = std::cend(seq);
    print(begin, end);
    }
    29

    View Slide

  30. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = std::cbegin(seq);
    const char * end = std::cend(seq);
    print(begin, end);
    }
    30
    These helpers are generic (type independent).
    The type of the iterator depends on the type
    of the sequence.
    We can use type deduction to get the correct
    type for our iterators.

    View Slide

  31. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = std::cbegin(seq);
    const char * end = std::cend(seq);
    print(begin, end);
    }
    31

    View Slide

  32. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    const char * begin = std::cbegin(seq);
    const char * end = std::cend(seq);
    print(begin, end);
    }
    32
    De r pi ,
    I wa t y o t p e s ha n e
    "ri t d e" of s i li on...

    View Slide

  33. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    decltype(std::cbegin(seq)) begin = std::cbegin(seq);
    decltype(std::cend(seq)) end = std::cend(seq);
    print(begin, end);
    }
    33

    View Slide

  34. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    auto begin = std::cbegin(seq);
    auto end = std::cend(seq);
    print(begin, end);
    }
    34

    View Slide

  35. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    auto begin = std::cbegin(seq);
    auto end = std::cend(seq);
    print(begin, end);
    }
    35

    View Slide

  36. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (const char * it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    auto begin = std::cbegin(seq);
    auto end = std::cend(seq);
    print(begin, end);
    }
    36

    View Slide

  37. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    auto begin = std::cbegin(seq);
    auto end = std::cend(seq);
    print(begin, end);
    }
    37

    View Slide

  38. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    auto begin = std::cbegin(seq);
    auto end = std::cend(seq);
    print(begin, end);
    }
    38

    View Slide

  39. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    auto begin = std::cbegin(seq);
    auto end = std::cend(seq);
    print(begin, end);
    }
    39
    Hello
    ..
    3
    type deduction and auto

    View Slide

  40. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    auto begin = std::cbegin(seq);
    auto end = std::cend(seq);
    print(begin, end);
    }
    40

    View Slide

  41. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    auto begin = std::cbegin(seq);
    auto end = std::cend(seq);
    print(begin, end);
    }
    41

    View Slide

  42. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    auto begin{std::cbegin(seq)};
    auto end = std::cend(seq);
    print(begin, end);
    }
    42

    View Slide

  43. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    auto begin{std::cbegin(seq)};
    auto end = std::cend(seq);
    print(begin, end);
    }
    43

    View Slide

  44. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    auto begin{std::cbegin(seq)};
    auto end{std::cend(seq)};
    print(begin, end);
    }
    44

    View Slide

  45. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it = begin; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    auto begin{std::cbegin(seq)};
    auto end{std::cend(seq)};
    print(begin, end);
    }
    45

    View Slide

  46. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it{begin}; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    auto begin{std::cbegin(seq)};
    auto end{std::cend(seq)};
    print(begin, end);
    }
    46

    View Slide

  47. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it{begin}; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[] = {'H', 'e', 'l', 'l', 'o'};
    auto begin{std::cbegin(seq)};
    auto end{std::cend(seq)};
    print(begin, end);
    }
    47

    View Slide

  48. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it{begin}; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    auto begin{std::cbegin(seq)};
    auto end{std::cend(seq)};
    print(begin, end);
    }
    48

    View Slide

  49. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it{begin}; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    auto begin{std::cbegin(seq)};
    auto end{std::cend(seq)};
    print(begin, end);
    }
    49

    View Slide

  50. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it{begin}; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    auto begin{std::cbegin(seq)};
    auto end{std::cend(seq)};
    print(begin, end);
    }
    50
    Many consider {}-initialization (aka brace
    initializers) to be superior. They give some
    extra type checking and other features.
    (but looks quite ugly, IMHO)

    View Slide

  51. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it{begin}; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    auto begin{std::cbegin(seq)};
    auto end{std::cend(seq)};
    print(begin, end);
    }
    51

    View Slide

  52. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it{begin}; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    auto begin{std::cbegin(seq)};
    auto end{std::cend(seq)};
    print(begin, end);
    }
    52
    Hello
    ..
    4
    {} initialization

    View Slide

  53. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it{begin}; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    auto begin{std::cbegin(seq)};
    auto end{std::cend(seq)};
    print(begin, end);
    }
    53
    Let's clean up a bit...

    View Slide

  54. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it{begin}; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    auto begin{std::cbegin(seq)};
    auto end{std::cend(seq)};
    print(begin, end);
    }
    54

    View Slide

  55. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it{begin}; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    auto end{std::cend(seq)};
    print(std::cbegin(seq), end);
    }
    55

    View Slide

  56. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it{begin}; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    auto end{std::cend(seq)};
    print(std::cbegin(seq), end);
    }
    56

    View Slide

  57. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it{begin}; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    57

    View Slide

  58. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it{begin}; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    58

    View Slide

  59. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it{begin}; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    59

    View Slide

  60. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it{begin}; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    60

    View Slide

  61. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    for (auto it{begin}; it != end; ++it)
    std::putchar(*it);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    61
    This is a typical imperative for-loop. It is also
    common to use the declarative std::for_each
    algorithm for simple loops like this.

    View Slide

  62. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    std::for_each(begin, end, std::putchar);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    62

    View Slide

  63. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    std::for_each(begin, end, std::putchar);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    63

    View Slide

  64. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    std::for_each(begin, end, std::putchar);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    64

    View Slide

  65. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    std::for_each(begin, end, std::putchar);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    65
    Hello
    ..
    5
    std::for_each algorithm

    View Slide

  66. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    std::for_each(begin, end, std::putchar);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    66

    View Slide

  67. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    std::for_each(begin, end, std::putchar);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    67
    Passing iterator pairs is used all over in C++,
    in particular in the C++ standard library.
    We may also use a container...

    View Slide

  68. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    std::for_each(begin, end, std::putchar);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    68

    View Slide

  69. #include "required_headers.hpp"
    void print(const char * begin, const char * end)
    {
    std::for_each(begin, end, std::putchar);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    69

    View Slide

  70. #include "required_headers.hpp"
    template
    struct MyCharSeq
    {
    const char * begin() const { return &data_[0]; }
    const char * end() const { return &data_[N]; }
    char data_[N];
    };
    void print(const char * begin, const char * end)
    {
    std::for_each(begin, end, std::putchar);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    70

    View Slide

  71. #include "required_headers.hpp"
    template
    struct MyCharSeq
    {
    const char * begin() const { return &data_[0]; }
    const char * end() const { return &data_[N]; }
    char data_[N];
    };
    void print(const char * begin, const char * end)
    {
    std::for_each(begin, end, std::putchar);
    }
    int main()
    {
    const char seq[]{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    71

    View Slide

  72. #include "required_headers.hpp"
    template
    struct MyCharSeq
    {
    const char * begin() const { return &data_[0]; }
    const char * end() const { return &data_[N]; }
    char data_[N];
    };
    void print(const char * begin, const char * end)
    {
    std::for_each(begin, end, std::putchar);
    }
    int main()
    {
    MyCharSeq<5> seq{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    72

    View Slide

  73. #include "required_headers.hpp"
    template
    struct MyCharSeq
    {
    const char * begin() const { return &data_[0]; }
    const char * end() const { return &data_[N]; }
    char data_[N];
    };
    void print(const char * begin, const char * end)
    {
    std::for_each(begin, end, std::putchar);
    }
    int main()
    {
    MyCharSeq<5> seq{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    73
    ... and now we can pass a const ref

    View Slide

  74. #include "required_headers.hpp"
    template
    struct MyCharSeq
    {
    const char * begin() const { return &data_[0]; }
    const char * end() const { return &data_[N]; }
    char data_[N];
    };
    void print(const char * begin, const char * end)
    {
    std::for_each(begin, end, std::putchar);
    }
    int main()
    {
    MyCharSeq<5> seq{'H', 'e', 'l', 'l', 'o'};
    print(std::cbegin(seq), std::cend(seq));
    }
    74

    View Slide

  75. #include "required_headers.hpp"
    template
    struct MyCharSeq
    {
    const char * begin() const { return &data_[0]; }
    const char * end() const { return &data_[N]; }
    char data_[N];
    };
    void print(const MyCharSeq<5> & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    MyCharSeq<5> seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    75

    View Slide

  76. #include "required_headers.hpp"
    template
    struct MyCharSeq
    {
    const char * begin() const { return &data_[0]; }
    const char * end() const { return &data_[N]; }
    char data_[N];
    };
    void print(const MyCharSeq<5> & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    MyCharSeq<5> seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    76

    View Slide

  77. #include "required_headers.hpp"
    template
    struct MyCharSeq
    {
    const char * begin() const { return &data_[0]; }
    const char * end() const { return &data_[N]; }
    char data_[N];
    };
    void print(const MyCharSeq<5> & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    MyCharSeq<5> seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    77
    Hello
    ..
    6
    user-defined container
    pass by const ref

    View Slide

  78. #include "required_headers.hpp"
    template
    struct MyCharSeq
    {
    const char * begin() const { return &data_[0]; }
    const char * end() const { return &data_[N]; }
    char data_[N];
    };
    void print(const MyCharSeq<5> & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    MyCharSeq<5> seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    78

    View Slide

  79. #include "required_headers.hpp"
    template
    struct MyCharSeq
    {
    const char * begin() const { return &data_[0]; }
    const char * end() const { return &data_[N]; }
    char data_[N];
    };
    void print(const MyCharSeq<5> & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    MyCharSeq<5> seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    79
    In the C++ standard library there are many
    useful containers defined already. For
    example, std::array...

    View Slide

  80. #include "required_headers.hpp"
    template
    struct MyCharSeq
    {
    const char * begin() const { return &data_[0]; }
    const char * end() const { return &data_[N]; }
    char data_[N];
    };
    void print(const MyCharSeq<5> & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    MyCharSeq<5> seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    80

    View Slide

  81. #include "required_headers.hpp"
    void print(const std::array & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::array seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    81

    View Slide

  82. #include "required_headers.hpp"
    void print(const std::array & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::array seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    82

    View Slide

  83. #include "required_headers.hpp"
    void print(const std::array & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::array seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    83

    View Slide

  84. #include "required_headers.hpp"
    void print(const std::array & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::array seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    84

    View Slide

  85. #include "required_headers.hpp"
    void print(const std::array & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::array seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    85
    Hello
    ..
    7
    std::array

    View Slide

  86. #include "required_headers.hpp"
    void print(const std::array & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::array seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    86

    View Slide

  87. #include "required_headers.hpp"
    void print(const std::array & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::array seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    87
    ... and std::vector

    View Slide

  88. #include "required_headers.hpp"
    void print(const std::vector & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    88

    View Slide

  89. #include "required_headers.hpp"
    void print(const std::vector & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    89

    View Slide

  90. #include "required_headers.hpp"
    void print(const std::vector & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    90
    Hello
    ..
    8
    std::vector

    View Slide

  91. #include "required_headers.hpp"
    void print(const std::vector & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    91

    View Slide

  92. #include "required_headers.hpp"
    void print(const std::vector & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'H', 'e', 'l', 'l', 'o'};
    print(seq);
    }
    92

    View Slide

  93. #include "required_headers.hpp"
    void print(const std::vector & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', 'l', 'l', 'H', 'o'};
    print(seq);
    }
    93

    View Slide

  94. #include "required_headers.hpp"
    void print(const std::vector & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', 'l', 'l', 'H', 'o'};
    print(seq);
    }
    94
    Perhaps we need to rearrange the elements
    before printing out.

    View Slide

  95. #include "required_headers.hpp"
    void print(const std::vector & seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', 'l', 'l', 'H', 'o'};
    print(seq);
    }
    95
    Then we might want to pass by value so that
    we get a copy of the container.

    View Slide

  96. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', 'l', 'l', 'H', 'o'};
    print(seq);
    }
    96

    View Slide

  97. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', 'l', 'l', 'H', 'o'};
    print(seq);
    }
    97
    And now we can sort the elements.

    View Slide

  98. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', 'l', 'l', 'H', 'o'};
    print(seq);
    }
    98

    View Slide

  99. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', 'l', 'l', 'H', 'o'};
    print(seq);
    }
    99

    View Slide

  100. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', 'l', 'l', 'H', 'o'};
    print(seq);
    }
    100

    View Slide

  101. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', 'l', 'l', 'H', 'o'};
    print(seq);
    }
    101

    View Slide

  102. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', 'l', 'l', 'H', 'o'};
    print(seq);
    }
    102
    Hello
    ..
    9
    std::sort
    pass by value (copy)

    View Slide

  103. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', 'l', 'l', 'H', 'o'};
    print(seq);
    }
    103

    View Slide

  104. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', 'l', 'l', 'H', 'o'};
    print(seq);
    }
    104

    View Slide

  105. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    105

    View Slide

  106. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    106
    Here we have some superfluous punctuation
    characters that needs to be filtered out.

    View Slide

  107. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    107

    View Slide

  108. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    108

    View Slide

  109. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::sort(std::begin(seq), std::end(seq));
    seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    109

    View Slide

  110. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::sort(std::begin(seq), std::end(seq));
    seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    110
    We apply the erase-remove idiom with
    ispunct as a predicate.

    View Slide

  111. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::sort(std::begin(seq), std::end(seq));
    seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    111

    View Slide

  112. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::sort(std::begin(seq), std::end(seq));
    seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    112
    Hello
    ..
    10
    erase-remove idiom

    View Slide

  113. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::sort(std::begin(seq), std::end(seq));
    seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    113

    View Slide

  114. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::sort(std::begin(seq), std::end(seq));
    seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    114
    At this abstraction level it is easy to discover
    optimization opportunities.
    Here, it looks like we should filter out the
    elements first and *then* sort the container.

    View Slide

  115. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    std::sort(std::begin(seq), std::end(seq));
    seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    115

    View Slide

  116. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    116

    View Slide

  117. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    117

    View Slide

  118. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    118
    Another, now, obvious optimization is to let
    sort and for_each work on the
    subsequence after remove_if, making the
    erase step obsolete.

    View Slide

  119. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    119

    View Slide

  120. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    120

    View Slide

  121. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    121

    View Slide

  122. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    seq.erase(newend , std::end(seq));
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    122

    View Slide

  123. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    seq.erase(newend , std::end(seq));
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    123

    View Slide

  124. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    seq.erase(newend, std::end(seq));
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    124

    View Slide

  125. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    seq.erase(newend, std::end(seq));
    std::sort(std::begin(seq), std::end(seq));
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    125

    View Slide

  126. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    seq.erase(newend, std::end(seq));
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    126

    View Slide

  127. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    seq.erase(newend, std::end(seq));
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    127

    View Slide

  128. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    seq.erase(newend, std::end(seq));
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    128

    View Slide

  129. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    seq.erase(newend, std::end(seq));
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    129

    View Slide

  130. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    130

    View Slide

  131. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    131

    View Slide

  132. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    132

    View Slide

  133. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    133

    View Slide

  134. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    134
    Hello
    ..
    11
    algorithms and high level optimization

    View Slide

  135. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    135

    View Slide

  136. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    136
    As well as values, you can also pass function
    objects.
    Now we will let the caller provide the
    filter predicate.

    View Slide

  137. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    137

    View Slide

  138. #include "required_headers.hpp"
    void print(std::vector seq )
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq );
    }
    138

    View Slide

  139. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, ::ispunct);
    }
    139

    View Slide

  140. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, ::ispunct);
    }
    140

    View Slide

  141. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, ::ispunct);
    }
    141

    View Slide

  142. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, ::ispunct);
    }
    142

    View Slide

  143. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, ::ispunct);
    }
    143
    Hello
    ..
    12
    std::function

    View Slide

  144. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, ::ispunct);
    }
    144

    View Slide

  145. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, ::ispunct);
    }
    145
    Now we can pass in quite advanced filters.
    Let us create an old-school function object
    (aka functor).

    View Slide

  146. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, ::ispunct);
    }
    146

    View Slide

  147. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    struct MyFilter {
    MyFilter(std::set validchars) : validchars_(validchars) {}
    bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
    std::set validchars_;
    } myfilter({'h','e','l','o'});
    print(seq, ::ispunct);
    }
    147

    View Slide

  148. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    struct MyFilter {
    MyFilter(std::set validchars) : validchars_(validchars) {}
    bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
    std::set validchars_;
    } myfilter({'h','e','l','o'});
    print(seq, ::ispunct);
    }
    148

    View Slide

  149. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    struct MyFilter {
    MyFilter(std::set validchars) : validchars_(validchars) {}
    bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
    std::set validchars_;
    } myfilter({'h','e','l','o'});
    print(seq, myfilter);
    }
    149

    View Slide

  150. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    struct MyFilter {
    MyFilter(std::set validchars) : validchars_(validchars) {}
    bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
    std::set validchars_;
    } myfilter({'h','e','l','o'});
    print(seq, myfilter);
    }
    150
    Here we have a filter allowing just 4 letters.

    View Slide

  151. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    struct MyFilter {
    MyFilter(std::set validchars) : validchars_(validchars) {}
    bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
    std::set validchars_;
    } myfilter({'h','e','l','o'});
    print(seq, myfilter);
    }
    151
    Notice, the key trick here is to overload the
    call operator.

    View Slide

  152. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    struct MyFilter {
    MyFilter(std::set validchars) : validchars_(validchars) {}
    bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
    std::set validchars_;
    } myfilter({'h','e','l','o'});
    print(seq, myfilter);
    }
    152

    View Slide

  153. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    struct MyFilter {
    MyFilter(std::set validchars) : validchars_(validchars) {}
    bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
    std::set validchars_;
    } myfilter({'h','e','l','o'});
    print(seq, myfilter);
    }
    153
    Hello
    ..
    13
    function objects (aka functors)

    View Slide

  154. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    struct MyFilter {
    MyFilter(std::set validchars) : validchars_(validchars) {}
    bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
    std::set validchars_;
    } myfilter({'h','e','l','o'});
    print(seq, myfilter);
    }
    154

    View Slide

  155. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    struct MyFilter {
    MyFilter(std::set validchars) : validchars_(validchars) {}
    bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
    std::set validchars_;
    } myfilter({'h','e','l','o'});
    print(seq, myfilter);
    }
    155
    We can also use lambda expressions to
    create function objects.

    View Slide

  156. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    struct MyFilter {
    MyFilter(std::set validchars) : validchars_(validchars) {}
    bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
    std::set validchars_;
    } myfilter({'h','e','l','o'});
    print(seq, myfilter);
    }
    156

    View Slide

  157. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    struct MyFilter {
    MyFilter(std::set validchars) : validchars_(validchars) {}
    bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
    std::set validchars_;
    } myfilter({'h','e','l','o'});
    print(seq, myfilter);
    }
    157

    View Slide

  158. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    struct MyFilter {
    MyFilter(std::set validchars) : validchars_(validchars) {}
    bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
    std::set validchars_;
    } myfilter({'h','e','l','o'});
    print(seq, myfilter);
    }
    158

    View Slide

  159. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    //struct MyFilter {
    // MyFilter(std::set validchars) : validchars_(validchars) {}
    // bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
    // std::set validchars_;
    //} myfilter({'h','e','l','o'});
    auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
    print(seq, myfilter);
    }
    159

    View Slide

  160. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    //struct MyFilter {
    // MyFilter(std::set validchars) : validchars_(validchars) {}
    // bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
    // std::set validchars_;
    //} myfilter({'h','e','l','o'});
    auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
    print(seq, myfilter);
    }
    160

    View Slide

  161. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    //struct MyFilter {
    // MyFilter(std::set validchars) : validchars_(validchars) {}
    // bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
    // std::set validchars_;
    //} myfilter({'h','e','l','o'});
    auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
    print(seq, myfilter);
    }
    161
    The lambda is equivalent to our old-school
    functor.

    View Slide

  162. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    //struct MyFilter {
    // MyFilter(std::set validchars) : validchars_(validchars) {}
    // bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
    // std::set validchars_;
    //} myfilter({'h','e','l','o'});
    auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
    print(seq, myfilter);
    }
    162

    View Slide

  163. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
    print(seq, myfilter);
    }
    163

    View Slide

  164. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
    print(seq, myfilter);
    }
    164

    View Slide

  165. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
    print(seq, myfilter);
    }
    165
    Hello
    ..
    14
    lamda expression and generalized lambda capture

    View Slide

  166. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
    print(seq, myfilter);
    }
    166

    View Slide

  167. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
    print(seq, myfilter);
    }
    167
    Lambdas are often used as simple wrappers
    for existing functions.

    View Slide

  168. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
    print(seq, myfilter);
    }
    168

    View Slide

  169. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    auto myfilter = [](char ch) { return !std::isalpha(ch); };
    print(seq, myfilter);
    }
    169

    View Slide

  170. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    auto myfilter = [](char ch) { return !std::isalpha(ch); };
    print(seq, myfilter);
    }
    170

    View Slide

  171. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    171

    View Slide

  172. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    172

    View Slide

  173. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    173
    Hello
    ..
    15
    wrap functions with lambda expressions

    View Slide

  174. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    174

    View Slide

  175. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    175
    Let us rewrite print into
    something more generic.

    View Slide

  176. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    176

    View Slide

  177. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    177

    View Slide

  178. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    178

    View Slide

  179. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    179

    View Slide

  180. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    180

    View Slide

  181. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    181

    View Slide

  182. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    182

    View Slide

  183. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    183
    typename is needed here to help the compiler
    to look for a type, instead of a value.

    View Slide

  184. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    184

    View Slide

  185. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    185
    Hello
    ..
    16
    function template and dependent names

    View Slide

  186. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    186

    View Slide

  187. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    187
    Generic code is nice, but often you will
    need to specify certain requirements for
    the template arguments. Types are
    known at compile time, so we can use
    type traits and static assert to reason
    about template arguments.

    View Slide

  188. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    188

    View Slide

  189. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    189

    View Slide

  190. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    static_assert(std::is_integral::value);
    static_assert(std::is_invocable::value);
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    190

    View Slide

  191. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    static_assert(std::is_integral::value);
    static_assert(std::is_invocable::value);
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    191

    View Slide

  192. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    static_assert(std::is_integral::value);
    static_assert(std::is_invocable::value);
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    192
    Hello
    ..
    17
    type traits
    static assert

    View Slide

  193. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    static_assert(std::is_integral::value);
    static_assert(std::is_invocable::value);
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    193

    View Slide

  194. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    static_assert(std::is_integral::value);
    static_assert(std::is_invocable::value);
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    194
    With enable_if we can take this idea
    further and tell the compiler that if certain
    requirements are not met, then a particular
    template should not even be considered for
    instantiation.

    View Slide

  195. #include "required_headers.hpp"
    template
    void print(Seq seq, Filter filter)
    {
    static_assert(std::is_integral::value);
    static_assert(std::is_invocable::value);
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    195

    View Slide

  196. #include "required_headers.hpp"
    template typename = std::enable_if_t<
    std::is_integral::value &&
    std::is_invocable::value> >
    void print(Seq seq, Filter filter)
    {
    static_assert(std::is_integral::value);
    static_assert(std::is_invocable::value);
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    196

    View Slide

  197. #include "required_headers.hpp"
    template typename = std::enable_if_t<
    std::is_integral::value &&
    std::is_invocable::value> >
    void print(Seq seq, Filter filter)
    {
    static_assert(std::is_integral::value);
    static_assert(std::is_invocable::value);
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    197

    View Slide

  198. #include "required_headers.hpp"
    template typename = std::enable_if_t<
    std::is_integral::value &&
    std::is_invocable::value> >
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    198

    View Slide

  199. #include "required_headers.hpp"
    template typename = std::enable_if_t<
    std::is_integral::value &&
    std::is_invocable::value> >
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    199

    View Slide

  200. #include "required_headers.hpp"
    template typename = std::enable_if_t<
    std::is_integral::value &&
    std::is_invocable::value> >
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    200
    Hello
    ..
    18
    std::enable_if

    View Slide

  201. #include "required_headers.hpp"
    template typename = std::enable_if_t<
    std::is_integral::value &&
    std::is_invocable::value> >
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    201

    View Slide

  202. #include "required_headers.hpp"
    template typename = std::enable_if_t<
    std::is_integral::value &&
    std::is_invocable::value> >
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    202
    C++20 will probably get Concepts, here is
    approximately how it is supposed to work.

    View Slide

  203. #include "required_headers.hpp"
    template typename = std::enable_if_t<
    std::is_integral::value &&
    std::is_invocable::value> >
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    203

    View Slide

  204. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template typename = std::enable_if_t<
    std::is_integral::value &&
    std::is_invocable::value> >
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    204

    View Slide

  205. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template typename = std::enable_if_t<
    std::is_integral::value &&
    std::is_invocable::value> >
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    205

    View Slide

  206. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template requires MySeqConcept() && MyFilterConcept()
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    206

    View Slide

  207. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template requires MySeqConcept() && MyFilterConcept()
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    207

    View Slide

  208. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template requires MySeqConcept() && MyFilterConcept()
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    208
    Hello
    ..
    19
    concepts
    requires
    C++20?

    View Slide

  209. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template requires MySeqConcept() && MyFilterConcept()
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    209

    View Slide

  210. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template requires MySeqConcept() && MyFilterConcept()
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    210
    concepts can be used instead of the keyword
    typename in the template parameter list.

    View Slide

  211. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template requires MySeqConcept() && MyFilterConcept()
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    211

    View Slide

  212. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    212

    View Slide

  213. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    213

    View Slide

  214. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    214
    Hello
    ..
    20
    concepts as template parameters
    C++20?

    View Slide

  215. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    215

    View Slide

  216. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    216
    I am now going to show something that probably will not make
    it into C++20, and maybe never... However, with the current
    version of gcc (8.2.0) it is possible to play with the idea of
    using concepts instead of types in a function declaration. (The
    effect is that you are really declaring a template.)

    View Slide

  217. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    217
    First I need to make a small change in the
    iterator pair for the for_each since the Seq
    type will soon be replaced by a concept.

    View Slide

  218. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    218

    View Slide

  219. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    219

    View Slide

  220. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    template
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    220

    View Slide

  221. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    // template
    void print(MySeqConcept seq, MyFilterConcept filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    221

    View Slide

  222. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    // template
    void print(MySeqConcept seq, MyFilterConcept filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    222

    View Slide

  223. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    void print(MySeqConcept seq, MyFilterConcept filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    223

    View Slide

  224. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    void print(MySeqConcept seq, MyFilterConcept filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    224

    View Slide

  225. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    void print(MySeqConcept seq, MyFilterConcept filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    225
    Now that we are using the concept names in
    the function declaration, we can go further
    and rename them.

    View Slide

  226. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    void print(MySeqConcept seq, MyFilterConcept filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    226

    View Slide

  227. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    void print(MySeqConcept seq, MyFilterConcept filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    227

    View Slide

  228. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    void print(MySeqConcept seq, MyFilterConcept filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    228

    View Slide

  229. #include "required_headers.hpp"
    template
    concept bool MySeqConcept() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool MyFilterConcept() {
    return std::is_invocable::value;
    }
    void print(MySeqConcept seq, MyFilterConcept filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    229

    View Slide

  230. #include "required_headers.hpp"
    template
    concept bool Seq() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool Filter() {
    return std::is_invocable::value;
    }
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    230

    View Slide

  231. #include "required_headers.hpp"
    template
    concept bool Seq() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool Filter() {
    return std::is_invocable::value;
    }
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    231

    View Slide

  232. #include "required_headers.hpp"
    template
    concept bool Seq() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool Filter() {
    return std::is_invocable::value;
    }
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    232
    Hello
    ..
    21
    concepts in function declaration
    C++26?

    View Slide

  233. #include "required_headers.hpp"
    template
    concept bool Seq() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool Filter() {
    return std::is_invocable::value;
    }
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    233

    View Slide

  234. #include "required_headers.hpp"
    template
    concept bool Seq() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool Filter() {
    return std::is_invocable::value;
    }
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    234
    Enough templates and concepts for now.
    Let's simplify the code.

    View Slide

  235. #include "required_headers.hpp"
    template
    concept bool Seq() {
    // TODO: also check that sequence is sortable
    return std::is_integral::value;
    }
    template
    concept bool Filter() {
    return std::is_invocable::value;
    }
    void print(Seq seq, Filter filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    235

    View Slide

  236. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    236

    View Slide

  237. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    237

    View Slide

  238. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    238

    View Slide

  239. #include "required_headers.hpp"
    void print(std::vector seq, std::function filter)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq, [](char ch) { return !std::isalpha(ch); });
    }
    239

    View Slide

  240. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    240

    View Slide

  241. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    241
    For efficiency, we might want to
    pass by reference.

    View Slide

  242. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    242

    View Slide

  243. #include "required_headers.hpp"
    void print(std::vector & seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    243

    View Slide

  244. #include "required_headers.hpp"
    void print(std::vector & seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    244
    The key thing here is the & to avoid a copy
    operation. We pass the sequence by a so
    called lvalue reference. Since we are not
    using the sequence after the call to print, this
    might be an acceptable solution.

    View Slide

  245. #include "required_headers.hpp"
    void print(std::vector & seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    245

    View Slide

  246. #include "required_headers.hpp"
    void print(std::vector & seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    246
    Hello
    ..
    22
    pass by lvalue reference

    View Slide

  247. #include "required_headers.hpp"
    void print(std::vector & seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    247

    View Slide

  248. #include "required_headers.hpp"
    void print(std::vector & seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    248
    It would be nice to express ownership when
    passing references like this. Who owns the
    content of the object? With rvalue references
    and move semantics you can in our example
    express transfer of ownership with && and a
    std::move.

    View Slide

  249. #include "required_headers.hpp"
    void print(std::vector & seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(seq);
    }
    249

    View Slide

  250. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(std::move(seq));
    }
    250

    View Slide

  251. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(std::move(seq));
    }
    251

    View Slide

  252. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(std::move(seq));
    }
    252
    It is important to realize that std::move is
    just a cast from lvalue to rvalue.

    View Slide

  253. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(std::move(seq));
    }
    253

    View Slide

  254. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(std::move(seq));
    }
    254
    Hello
    ..
    23
    pass by rvalue reference
    std::move

    View Slide

  255. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(std::move(seq));
    }
    255

    View Slide

  256. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(std::move(seq));
    }
    256
    Now we will show how rvalue references can
    bind to objects without a name, eg a return
    value from a function.

    View Slide

  257. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(std::move(seq));
    }
    257

    View Slide

  258. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(std::move(seq));
    }
    258

    View Slide

  259. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(std::move(seq));
    }
    259

    View Slide

  260. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    print(std::move(seq));
    }
    260

    View Slide

  261. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    std::vector seq = greeting();
    print(std::move(seq));
    }
    261

    View Slide

  262. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    std::vector seq = greeting();
    print(std::move(seq));
    }
    262

    View Slide

  263. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    print(greeting());
    }
    263

    View Slide

  264. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    print(greeting());
    }
    264

    View Slide

  265. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    print(greeting());
    }
    265
    Due to return value optimization, copy
    elision, rvalues and move semantics,
    nothing will be copied here. All the elements
    (and the ownership) are just moved into the
    print function.

    View Slide

  266. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    print(greeting());
    }
    266

    View Slide

  267. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    print(greeting());
    }
    267
    Hello
    ..
    24
    return value optimization and copy elision

    View Slide

  268. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    print(greeting());
    }
    268

    View Slide

  269. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    print(greeting());
    }
    269
    std::vector has a move constructor, so
    here pass by value is just moving elements if
    we give it an rvalue.

    View Slide

  270. #include "required_headers.hpp"
    void print(std::vector && seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    print(greeting());
    }
    270

    View Slide

  271. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    print(greeting());
    }
    271

    View Slide

  272. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    print(greeting());
    }
    272

    View Slide

  273. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    print(greeting());
    }
    273
    Hello
    ..
    25
    std::vector move constructor

    View Slide

  274. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    print(greeting());
    }
    274

    View Slide

  275. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    print(greeting());
    }
    275
    When planning this presentation, I promised
    myself that I would show structural binding
    and if statement with initialization. Although
    a small detour, this is the time to show it.

    View Slide

  276. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    std::vector greeting()
    {
    return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
    }
    int main()
    {
    print(greeting());
    }
    276

    View Slide

  277. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    auto greeting()
    {
    return std::tuple,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42);
    }
    int main()
    {
    auto [str, answer] = greeting();
    if (answer == 42)
    print(str);
    }
    277

    View Slide

  278. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    auto greeting()
    {
    return std::tuple,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42);
    }
    int main()
    {
    auto [str, answer] = greeting();
    if (answer == 42)
    print(str);
    }
    278

    View Slide

  279. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    auto greeting()
    {
    return std::tuple,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42);
    }
    int main()
    {
    if (auto [str, answer] = greeting(); answer == 42)
    print(str);
    }
    279

    View Slide

  280. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    auto greeting()
    {
    return std::tuple,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42);
    }
    int main()
    {
    if (auto [str, answer] = greeting(); answer == 42)
    print(str);
    }
    280

    View Slide

  281. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    auto greeting()
    {
    return std::tuple,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42);
    }
    int main()
    {
    if (auto [str, answer] = greeting(); answer == 42)
    print(str);
    }
    281
    Hello
    ..
    26
    if statement with initializer
    std::tuple
    structural binding

    View Slide

  282. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    auto greeting()
    {
    return std::tuple,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42);
    }
    int main()
    {
    if (auto [str, answer] = greeting(); answer == 42)
    print(str);
    }
    282

    View Slide

  283. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    auto greeting()
    {
    return std::tuple,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42);
    }
    int main()
    {
    if (auto [str, answer] = greeting(); answer == 42)
    print(str);
    }
    283
    Now for something completely different!

    View Slide

  284. #include "required_headers.hpp"
    void print(std::vector seq)
    {
    auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
    std::sort(std::begin(seq), newend);
    std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
    }
    auto greeting()
    {
    return std::tuple,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42);
    }
    int main()
    {
    if (auto [str, answer] = greeting(); answer == 42)
    print(str);
    }
    284

    View Slide

  285. #include "required_headers.hpp"
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    285

    View Slide

  286. #include "required_headers.hpp"
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    286

    View Slide

  287. #include "required_headers.hpp"
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    287
    Notice that the elements are in the wrong order.

    View Slide

  288. #include "required_headers.hpp"
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    288

    View Slide

  289. #include "required_headers.hpp"
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    289
    No problem, just apply reverse iterators to get it right.

    View Slide

  290. #include "required_headers.hpp"
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    290

    View Slide

  291. #include "required_headers.hpp"
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    291
    Hello
    ..
    27
    reverse iterators

    View Slide

  292. #include "required_headers.hpp"
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    292

    View Slide

  293. #include "required_headers.hpp"
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    293
    Let's write our very own putchar and put it in
    our very own namespace.

    View Slide

  294. #include "required_headers.hpp"
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    294

    View Slide

  295. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    295

    View Slide

  296. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    296

    View Slide

  297. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    297
    Hello
    ..
    28
    namespace and std::flush

    View Slide

  298. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    298

    View Slide

  299. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    299
    Let's introduce a type writer effect by adding
    a small pause before printing each character.

    View Slide

  300. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    300

    View Slide

  301. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    301

    View Slide

  302. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    302

    View Slide

  303. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    303

    View Slide

  304. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    304
    H

    View Slide

  305. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    305
    He

    View Slide

  306. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    306
    Hel

    View Slide

  307. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    307
    Hell

    View Slide

  308. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    308
    Hello

    View Slide

  309. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    309
    Hello
    ..
    29
    chrono and sleep_for

    View Slide

  310. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    310

    View Slide

  311. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    311
    We will soon show how to run code
    asynchronously. But first we show an
    alternative way to invoke a function.

    View Slide

  312. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    312

    View Slide

  313. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    std::invoke(print, seq);
    }
    313

    View Slide

  314. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto n = std::invoke(print, seq);
    std::cout << n;
    }
    314

    View Slide

  315. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto n = std::invoke(print, seq);
    std::cout << n;
    }
    315

    View Slide

  316. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto n = std::invoke(print, seq);
    std::cout << n;
    }
    316
    Hello5
    ..
    30
    std::invoke

    View Slide

  317. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto n = std::invoke(print, seq);
    std::cout << n;
    }
    317

    View Slide

  318. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto n = std::invoke(print, seq);
    std::cout << n;
    }
    318
    Now we can replace std::invoke with
    std::async

    View Slide

  319. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto n = std::invoke(print, seq);
    std::cout << n;
    }
    319

    View Slide

  320. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(print, seq);
    auto n = f.get();
    std::cout << n;
    }
    320

    View Slide

  321. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(print, seq);
    auto n = f.get();
    std::cout << n;
    }
    321

    View Slide

  322. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(print, seq);
    auto n = f.get();
    std::cout << n;
    }
    322
    std::async returns a future that holds a
    value that we can retrieve later. Notice how
    invoking and getting the result is now two
    separate statements, this allow us to
    something while it is executing.

    View Slide

  323. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(print, seq);
    auto n = f.get();
    std::cout << n;
    }
    323

    View Slide

  324. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(print, seq);
    auto n = f.get();
    std::cout << n;
    }
    324

    View Slide

  325. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    325

    View Slide

  326. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    326

    View Slide

  327. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    327
    .H.el.l..o.....5
    ..
    31
    this what I often get on my
    machine...
    std::async
    promise and future

    View Slide

  328. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    328

    View Slide

  329. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    329
    The default launch policy depends on your
    compiler/runtime. By explicitly specify the
    launch policy you can for example defer
    execution until you call the get() function.
    This can be useful, in particular when
    debugging.

    View Slide

  330. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    330

    View Slide

  331. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::deferred, print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    331

    View Slide

  332. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::deferred, print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    332

    View Slide

  333. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::deferred, print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    333
    ..........Hello5
    ..
    32
    deferred launch policy

    View Slide

  334. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::deferred, print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    334

    View Slide

  335. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::deferred, print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    335
    Or you can specify that you want threads to
    be created and started.

    View Slide

  336. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::deferred, print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    336

    View Slide

  337. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::async, print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    337

    View Slide

  338. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::async, print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    338

    View Slide

  339. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::async, print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    339
    .H.el.l..o.....5
    ..
    33
    async launch policy

    View Slide

  340. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::async, print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    340

    View Slide

  341. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::async, print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    341
    Ok, I just can not resist... let's have some fun
    with overloading the multiplication operator
    and create a repeat function. (Don't do this in
    your codebase...)

    View Slide

  342. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::async, print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    342

    View Slide

  343. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    template
    void operator*(int n, Func f)
    {
    while (n--)
    f();
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::async, print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    343

    View Slide

  344. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    template
    void operator*(int n, Func f)
    {
    while (n--)
    f();
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::async, print, seq);
    for (int i = 10; i; --i)
    my::putchar('.');
    auto n = f.get();
    std::cout << n;
    }
    344

    View Slide

  345. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    template
    void operator*(int n, Func f)
    {
    while (n--)
    f();
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::async, print, seq);
    10 * []{ my::putchar('.'); };
    auto n = f.get();
    std::cout << n;
    }
    345

    View Slide

  346. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    template
    void operator*(int n, Func f)
    {
    while (n--)
    f();
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::async, print, seq);
    10 * []{ my::putchar('.'); };
    auto n = f.get();
    std::cout << n;
    }
    346

    View Slide

  347. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    template
    void operator*(int n, Func f)
    {
    while (n--)
    f();
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::async, print, seq);
    10 * []{ my::putchar('.'); };
    auto n = f.get();
    std::cout << n;
    }
    347
    .H.el.l..o.....5
    ..
    34
    silly operator overload (don't do this)

    View Slide

  348. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    template
    void operator*(int n, Func f)
    {
    while (n--)
    f();
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::async, print, seq);
    10 * []{ my::putchar('.'); };
    auto n = f.get();
    std::cout << n;
    }
    348

    View Slide

  349. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    template
    void operator*(int n, Func f)
    {
    while (n--)
    f();
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::async, print, seq);
    10 * []{ my::putchar('.'); };
    auto n = f.get();
    std::cout << n;
    }
    349
    I am now going to show user-defined literals,
    but first we clean up the code.

    View Slide

  350. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    template
    void operator*(int n, Func f)
    {
    while (n--)
    f();
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::async, print, seq);
    10 * []{ my::putchar('.'); };
    auto n = f.get();
    std::cout << n;
    }
    350

    View Slide

  351. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::async, print, seq);
    auto n = f.get();
    std::cout << n;
    }
    351

    View Slide

  352. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    auto f = std::async(std::launch::async, print, seq);
    auto n = f.get();
    std::cout << n;
    }
    352

    View Slide

  353. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    353

    View Slide

  354. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    354

    View Slide

  355. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    355
    Here we go, user-defined literals!

    View Slide

  356. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    356

    View Slide

  357. #include "required_headers.hpp"
    auto operator"" _ms(unsigned long long n)
    {
    return std::chrono::milliseconds(n);
    }
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    357

    View Slide

  358. #include "required_headers.hpp"
    auto operator"" _ms(unsigned long long n)
    {
    return std::chrono::milliseconds(n);
    }
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    358

    View Slide

  359. #include "required_headers.hpp"
    auto operator"" _ms(unsigned long long n)
    {
    return std::chrono::milliseconds(n);
    }
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500_ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    359

    View Slide

  360. #include "required_headers.hpp"
    auto operator"" _ms(unsigned long long n)
    {
    return std::chrono::milliseconds(n);
    }
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500_ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    360

    View Slide

  361. #include "required_headers.hpp"
    auto operator"" _ms(unsigned long long n)
    {
    return std::chrono::milliseconds(n);
    }
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500_ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    361

    View Slide

  362. #include "required_headers.hpp"
    auto operator"" _ms(unsigned long long n)
    {
    return std::chrono::milliseconds(n);
    }
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500_ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    362
    H

    View Slide

  363. #include "required_headers.hpp"
    auto operator"" _ms(unsigned long long n)
    {
    return std::chrono::milliseconds(n);
    }
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500_ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    363
    He

    View Slide

  364. #include "required_headers.hpp"
    auto operator"" _ms(unsigned long long n)
    {
    return std::chrono::milliseconds(n);
    }
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500_ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    364
    Hel

    View Slide

  365. #include "required_headers.hpp"
    auto operator"" _ms(unsigned long long n)
    {
    return std::chrono::milliseconds(n);
    }
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500_ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    365
    Hell

    View Slide

  366. #include "required_headers.hpp"
    auto operator"" _ms(unsigned long long n)
    {
    return std::chrono::milliseconds(n);
    }
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500_ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    366
    Hello

    View Slide

  367. #include "required_headers.hpp"
    auto operator"" _ms(unsigned long long n)
    {
    return std::chrono::milliseconds(n);
    }
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500_ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    367
    Hello
    ..
    35
    user-defined literals (UDL)

    View Slide

  368. #include "required_headers.hpp"
    auto operator"" _ms(unsigned long long n)
    {
    return std::chrono::milliseconds(n);
    }
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500_ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    368

    View Slide

  369. #include "required_headers.hpp"
    auto operator"" _ms(unsigned long long n)
    {
    return std::chrono::milliseconds(n);
    }
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500_ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    369
    The C++ standard library already comes with
    a handful of useful user-defined literals.

    View Slide

  370. #include "required_headers.hpp"
    auto operator"" _ms(unsigned long long n)
    {
    return std::chrono::milliseconds(n);
    }
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500_ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    370

    View Slide

  371. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    371

    View Slide

  372. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    372

    View Slide

  373. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    373
    Hello
    ..
    36
    std::chrono_literals

    View Slide

  374. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    374

    View Slide

  375. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500ms);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    375

    View Slide

  376. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500000000ns);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    376

    View Slide

  377. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500000000ns);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    377

    View Slide

  378. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500000000ns);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    378
    Even nanoseconds.

    View Slide

  379. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500000000ns);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    379
    Even nanoseconds.
    Phew, this is hard to read...

    View Slide

  380. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500000000ns);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    380

    View Slide

  381. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500000000ns);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    381

    View Slide

  382. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500'000'000ns);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    382

    View Slide

  383. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500'000'000ns);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    383
    Better?

    View Slide

  384. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500'000'000ns);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    384

    View Slide

  385. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500'000'000ns);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    385
    Hello
    ..
    37
    digits separator

    View Slide

  386. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500'000'000ns);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    386

    View Slide

  387. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500'000'000ns);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    387
    Now for something completely different...

    View Slide

  388. #include "required_headers.hpp"
    using namespace std::chrono_literals;
    namespace my {
    void putchar(char ch)
    {
    std::this_thread::sleep_for(500'000'000ns);
    std::cout << ch << std::flush;
    }
    }
    std::size_t print(std::vector seq)
    {
    std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
    return std::size(seq);
    }
    int main()
    {
    std::vector seq{'o', 'l', 'l', 'e', 'H'};
    print(seq);
    }
    388

    View Slide

  389. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::for_each(&s[bi], &s[ei], std::putchar);
    }
    389

    View Slide

  390. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::for_each(&s[bi], &s[ei], std::putchar);
    }
    390

    View Slide

  391. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::for_each(&s[bi], &s[ei], std::putchar);
    }
    391
    Hello
    ..
    38
    std::string

    View Slide

  392. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::for_each(&s[bi], &s[ei], std::putchar);
    }
    392

    View Slide

  393. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::for_each(&s[bi], &s[ei], std::putchar);
    }
    393
    After finding the beginning and the end, we
    can create a view into the string...

    View Slide

  394. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::for_each(&s[bi], &s[ei], std::putchar);
    }
    394

    View Slide

  395. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    std::for_each(&s[bi], &s[ei], std::putchar);
    }
    395

    View Slide

  396. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    std::for_each(&s[bi], &s[ei], std::putchar);
    }
    396

    View Slide

  397. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    std::for_each(std::cbegin(sv), std::cend(sv), std::putchar);
    }
    397

    View Slide

  398. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    std::for_each(std::cbegin(sv), std::cend(sv), std::putchar);
    }
    398

    View Slide

  399. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    std::for_each(std::cbegin(sv), std::cend(sv), std::putchar);
    }
    399
    And since this is just a trivial pass from begin
    to end, we can also use the very cute
    range-for.

    View Slide

  400. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    std::for_each(std::cbegin(sv), std::cend(sv), std::putchar);
    }
    400

    View Slide

  401. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    std::for_each(std::cbegin(sv), std::cend(sv), std::putchar);
    }
    401

    View Slide

  402. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    402

    View Slide

  403. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    403

    View Slide

  404. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    404
    Hello
    ..
    39
    std::string_view
    range-for

    View Slide

  405. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    405

    View Slide

  406. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    406
    The C++ standard library also comes with
    predefined string literals.

    View Slide

  407. #include "required_headers.hpp"
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    407

    View Slide

  408. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    408

    View Slide

  409. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    std::string s = "................Hello..........";
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    409

    View Slide

  410. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    std::string s = "................Hello.........."s;
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    410

    View Slide

  411. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    std::string s = "................Hello.........."s;
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    411

    View Slide

  412. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    auto s = "................Hello.........."s;
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    412

    View Slide

  413. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    auto s = "................Hello.........."s;
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    413

    View Slide

  414. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    auto s = "................Hello.........."s;
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    414
    There is also a string_view literal...

    View Slide

  415. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    auto s = "................Hello.........."s;
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    415

    View Slide

  416. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    auto s = "................Hello.........."sv;
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    416

    View Slide

  417. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    auto s = "................Hello.........."sv;
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    417

    View Slide

  418. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    auto s = "................Hello.........."sv;
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    418
    Hello
    ..
    40
    string literals

    View Slide

  419. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    auto s = "................Hello.........."sv;
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    419

    View Slide

  420. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    auto s = "................Hello.........."sv;
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    420
    Notice that most of this could be computed
    in compile time. Indeed, with constexpr you
    can force the compiler to compute stuff if
    possible.

    View Slide

  421. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    auto s = "................Hello.........."sv;
    std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    std::size_t len = ei - bi;
    std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    421

    View Slide

  422. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    constexpr auto s = "................Hello.........."sv;
    constexpr std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    constexpr std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    constexpr std::size_t len = ei - bi;
    constexpr std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    422

    View Slide

  423. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    constexpr auto s = "................Hello.........."sv;
    constexpr std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    constexpr std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    constexpr std::size_t len = ei - bi;
    constexpr std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    423

    View Slide

  424. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    constexpr auto s = "................Hello.........."sv;
    constexpr std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    constexpr std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    constexpr std::size_t len = ei - bi;
    constexpr std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    424
    Hello
    ..
    41
    constexpr

    View Slide

  425. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    constexpr auto s = "................Hello.........."sv;
    constexpr std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    constexpr std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    constexpr std::size_t len = ei - bi;
    constexpr std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    425

    View Slide

  426. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    constexpr auto s = "................Hello.........."sv;
    constexpr std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    constexpr std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    constexpr std::size_t len = ei - bi;
    constexpr std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    426
    And last, but not least...

    View Slide

  427. #include "required_headers.hpp"
    using namespace std::literals;
    int main()
    {
    constexpr auto s = "................Hello.........."sv;
    constexpr std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s));
    constexpr std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s));
    constexpr std::size_t len = ei - bi;
    constexpr std::string_view sv(&s[bi], len);
    for (char c : sv)
    std::putchar(c);
    }
    427

    View Slide

  428. #include
    int main()
    {
    std::cout << "Hello\n";
    }
    428

    View Slide

  429. #include
    int main()
    {
    std::cout << "Hello\n";
    }
    429
    It is possible to print out "Hello" just like this.

    View Slide

  430. #include
    int main()
    {
    std::cout << "Hello\n";
    }
    430

    View Slide

  431. #include
    int main()
    {
    std::cout << "Hello\n";
    }
    431
    Hello
    ..
    42
    just "Hello"

    View Slide

  432. 432
    !

    View Slide

  433. 433
    1. iterators
    2. std::cbegin() / std::cend()
    3. type deduction and auto
    4. {} initialization (aka brace initialization)
    5. std::for_each
    6. user-defined container and pass by const ref
    7. std::array
    8. std::vector
    9. std::sort and pass by value (copy)
    10. erase-remove idiom
    11. algorithms and high level optimization
    12. std::function
    13. function objects (aka functors)
    14. lambda expression and generalized lambda capture
    15. wrap functions with lambda expressions
    16. function template and dependent names
    17. type traits and static assert
    18. enable_if
    19. concepts and requires (C++20?)
    20. concepts as template parameters (C++20?)
    21. concepts in function declaration (C++23?)
    22. pass by lvalue reference
    23. pass by rvalue reference and std::move
    24. return value optimization and copy elision
    25. the std::vector move constructor
    26. std::tuple, structural binding and if statement with initializer
    27. reverse iterators
    28. namespace and my::putchar
    29. chrono and sleep_for
    30. std::invoke
    31. async, future and promise
    32. std::launch::deferred
    33. std::launch::async
    34. silly operator overload (don't do this)
    35. user-defined literals
    36. std::chrono_literals
    37. digits separator
    38. std::string
    39. std::string_view and range-for
    40. string literals
    41. constexpr
    42. just "Hello"

    View Slide

  434. 434

    View Slide

  435. 435
    Still here? OK, one more then...

    View Slide

  436. #include "required_headers.hpp"
    namespace my {
    void putchar(char ch, long delay)
    {
    std::this_thread::sleep_for(std::chrono::milliseconds(delay));
    std::cout << ch << std::flush;
    }
    }
    void print(std::vector seq)
    {
    std::vector> futures(std::size(seq));
    for (char ch : seq)
    futures.emplace_back(std::async(my::putchar, ch, ch));
    }
    int main()
    {
    std::vector seq{'e', 'l', 'H', 'o', 'l'};
    print(seq);
    }
    436
    Hello
    ..
    sleep sort

    View Slide