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
  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!
  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
  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.
  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.
  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.
  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.
  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
  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
  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
  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
  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.
  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
  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
  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
  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...
  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
  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
  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
  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
  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.
  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
  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
  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
  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
  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
  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
  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()
  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
  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.
  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
  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...
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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
  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)
  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
  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
  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...
  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
  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
  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
  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
  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
  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
  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
  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.
  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
  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
  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
  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
  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
  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...
  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
  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
  70. #include "required_headers.hpp" template <size_t N> 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
  71. #include "required_headers.hpp" template <size_t N> 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
  72. #include "required_headers.hpp" template <size_t N> 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
  73. #include "required_headers.hpp" template <size_t N> 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
  74. #include "required_headers.hpp" template <size_t N> 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
  75. #include "required_headers.hpp" template <size_t N> 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
  76. #include "required_headers.hpp" template <size_t N> 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
  77. #include "required_headers.hpp" template <size_t N> 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
  78. #include "required_headers.hpp" template <size_t N> 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
  79. #include "required_headers.hpp" template <size_t N> 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...
  80. #include "required_headers.hpp" template <size_t N> 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
  81. #include "required_headers.hpp" void print(const std::array<char, 5> & seq) { std::for_each(std::cbegin(seq),

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    std::putchar); } int main() { std::vector<char> 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.
  96. #include "required_headers.hpp" void print(std::vector<char> seq) { std::for_each(std::cbegin(seq), std::cend(seq), std::putchar); }

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

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

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

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

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

    std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 108
  102. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 109
  103. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 110 We apply the erase-remove idiom with ispunct as a predicate.
  104. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 111
  105. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 112 Hello .. 10 erase-remove idiom
  106. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 113
  107. #include "required_headers.hpp" void print(std::vector<char> 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<char> 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.
  108. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 115
  109. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 116
  110. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 117
  111. #include "required_headers.hpp" void print(std::vector<char> 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<char> 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.
  112. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 119
  113. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 120
  114. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 121
  115. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 122
  116. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 123
  117. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 124
  118. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 125
  119. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 126
  120. #include "required_headers.hpp" void print(std::vector<char> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 127
  121. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 128
  122. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 129
  123. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 130
  124. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 131
  125. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 132
  126. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 133
  127. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 134 Hello .. 11 algorithms and high level optimization
  128. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 135
  129. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> 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.
  130. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 137
  131. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq ); } 138
  132. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, ::ispunct); } 139
  133. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, ::ispunct); } 140
  134. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, ::ispunct); } 141
  135. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, ::ispunct); } 142
  136. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, ::ispunct); } 143 Hello .. 12 std::function
  137. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, ::ispunct); } 144
  138. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> 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).
  139. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, ::ispunct); } 146
  140. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; struct MyFilter { MyFilter(std::set<char> validchars) : validchars_(validchars) {} bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); } std::set<char> validchars_; } myfilter({'h','e','l','o'}); print(seq, ::ispunct); } 147
  141. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; struct MyFilter { MyFilter(std::set<char> validchars) : validchars_(validchars) {} bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); } std::set<char> validchars_; } myfilter({'h','e','l','o'}); print(seq, ::ispunct); } 148
  142. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; struct MyFilter { MyFilter(std::set<char> validchars) : validchars_(validchars) {} bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); } std::set<char> validchars_; } myfilter({'h','e','l','o'}); print(seq, myfilter); } 149
  143. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; struct MyFilter { MyFilter(std::set<char> validchars) : validchars_(validchars) {} bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); } std::set<char> validchars_; } myfilter({'h','e','l','o'}); print(seq, myfilter); } 150 Here we have a filter allowing just 4 letters.
  144. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; struct MyFilter { MyFilter(std::set<char> validchars) : validchars_(validchars) {} bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); } std::set<char> validchars_; } myfilter({'h','e','l','o'}); print(seq, myfilter); } 151 Notice, the key trick here is to overload the call operator.
  145. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; struct MyFilter { MyFilter(std::set<char> validchars) : validchars_(validchars) {} bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); } std::set<char> validchars_; } myfilter({'h','e','l','o'}); print(seq, myfilter); } 152
  146. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; struct MyFilter { MyFilter(std::set<char> validchars) : validchars_(validchars) {} bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); } std::set<char> validchars_; } myfilter({'h','e','l','o'}); print(seq, myfilter); } 153 Hello .. 13 function objects (aka functors)
  147. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; struct MyFilter { MyFilter(std::set<char> validchars) : validchars_(validchars) {} bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); } std::set<char> validchars_; } myfilter({'h','e','l','o'}); print(seq, myfilter); } 154
  148. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; struct MyFilter { MyFilter(std::set<char> validchars) : validchars_(validchars) {} bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); } std::set<char> validchars_; } myfilter({'h','e','l','o'}); print(seq, myfilter); } 155 We can also use lambda expressions to create function objects.
  149. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; struct MyFilter { MyFilter(std::set<char> validchars) : validchars_(validchars) {} bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); } std::set<char> validchars_; } myfilter({'h','e','l','o'}); print(seq, myfilter); } 156
  150. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; struct MyFilter { MyFilter(std::set<char> validchars) : validchars_(validchars) {} bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); } std::set<char> validchars_; } myfilter({'h','e','l','o'}); print(seq, myfilter); } 157
  151. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; struct MyFilter { MyFilter(std::set<char> validchars) : validchars_(validchars) {} bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); } std::set<char> validchars_; } myfilter({'h','e','l','o'}); print(seq, myfilter); } 158
  152. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; //struct MyFilter { // MyFilter(std::set<char> validchars) : validchars_(validchars) {} // bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); } // std::set<char> validchars_; //} myfilter({'h','e','l','o'}); auto myfilter = [vc=std::set<char>{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); }; print(seq, myfilter); } 159
  153. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; //struct MyFilter { // MyFilter(std::set<char> validchars) : validchars_(validchars) {} // bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); } // std::set<char> validchars_; //} myfilter({'h','e','l','o'}); auto myfilter = [vc=std::set<char>{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); }; print(seq, myfilter); } 160
  154. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; //struct MyFilter { // MyFilter(std::set<char> validchars) : validchars_(validchars) {} // bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); } // std::set<char> validchars_; //} myfilter({'h','e','l','o'}); auto myfilter = [vc=std::set<char>{'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.
  155. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; //struct MyFilter { // MyFilter(std::set<char> validchars) : validchars_(validchars) {} // bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); } // std::set<char> validchars_; //} myfilter({'h','e','l','o'}); auto myfilter = [vc=std::set<char>{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); }; print(seq, myfilter); } 162
  156. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; auto myfilter = [vc=std::set<char>{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); }; print(seq, myfilter); } 163
  157. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; auto myfilter = [vc=std::set<char>{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); }; print(seq, myfilter); } 164
  158. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; auto myfilter = [vc=std::set<char>{'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
  159. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; auto myfilter = [vc=std::set<char>{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); }; print(seq, myfilter); } 166
  160. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; auto myfilter = [vc=std::set<char>{'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.
  161. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; auto myfilter = [vc=std::set<char>{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); }; print(seq, myfilter); } 168
  162. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; auto myfilter = [](char ch) { return !std::isalpha(ch); }; print(seq, myfilter); } 169
  163. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; auto myfilter = [](char ch) { return !std::isalpha(ch); }; print(seq, myfilter); } 170
  164. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 171
  165. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 172
  166. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 173 Hello .. 15 wrap functions with lambda expressions
  167. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 174
  168. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 175 Let us rewrite print into something more generic.
  169. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 176
  170. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 177
  171. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (char)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 178
  172. #include "required_headers.hpp" template <typename Seq, typename Filter> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 179
  173. #include "required_headers.hpp" template <typename Seq, typename Filter> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 180
  174. #include "required_headers.hpp" template <typename Seq, typename Filter> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 181
  175. #include "required_headers.hpp" template <typename Seq, typename Filter> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 182
  176. #include "required_headers.hpp" template <typename Seq, typename Filter> 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<char> 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.
  177. #include "required_headers.hpp" template <typename Seq, typename Filter> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 184
  178. #include "required_headers.hpp" template <typename Seq, typename Filter> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 185 Hello .. 16 function template and dependent names
  179. #include "required_headers.hpp" template <typename Seq, typename Filter> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 186
  180. #include "required_headers.hpp" template <typename Seq, typename Filter> 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<char> 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.
  181. #include "required_headers.hpp" template <typename Seq, typename Filter> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 188
  182. #include "required_headers.hpp" template <typename Seq, typename Filter> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 189
  183. #include "required_headers.hpp" template <typename Seq, typename Filter> void print(Seq seq,

    Filter filter) { static_assert(std::is_integral<typename Seq::value_type>::value); static_assert(std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 190
  184. #include "required_headers.hpp" template <typename Seq, typename Filter> void print(Seq seq,

    Filter filter) { static_assert(std::is_integral<typename Seq::value_type>::value); static_assert(std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 191
  185. #include "required_headers.hpp" template <typename Seq, typename Filter> void print(Seq seq,

    Filter filter) { static_assert(std::is_integral<typename Seq::value_type>::value); static_assert(std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 192 Hello .. 17 type traits static assert
  186. #include "required_headers.hpp" template <typename Seq, typename Filter> void print(Seq seq,

    Filter filter) { static_assert(std::is_integral<typename Seq::value_type>::value); static_assert(std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 193
  187. #include "required_headers.hpp" template <typename Seq, typename Filter> void print(Seq seq,

    Filter filter) { static_assert(std::is_integral<typename Seq::value_type>::value); static_assert(std::is_invocable<Filter, int>::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<char> 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.
  188. #include "required_headers.hpp" template <typename Seq, typename Filter> void print(Seq seq,

    Filter filter) { static_assert(std::is_integral<typename Seq::value_type>::value); static_assert(std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 195
  189. #include "required_headers.hpp" template <typename Seq, typename Filter, typename = std::enable_if_t<

    std::is_integral<typename Seq::value_type>::value && std::is_invocable<Filter, int>::value> > void print(Seq seq, Filter filter) { static_assert(std::is_integral<typename Seq::value_type>::value); static_assert(std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 196
  190. #include "required_headers.hpp" template <typename Seq, typename Filter, typename = std::enable_if_t<

    std::is_integral<typename Seq::value_type>::value && std::is_invocable<Filter, int>::value> > void print(Seq seq, Filter filter) { static_assert(std::is_integral<typename Seq::value_type>::value); static_assert(std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 197
  191. #include "required_headers.hpp" template <typename Seq, typename Filter, typename = std::enable_if_t<

    std::is_integral<typename Seq::value_type>::value && std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 198
  192. #include "required_headers.hpp" template <typename Seq, typename Filter, typename = std::enable_if_t<

    std::is_integral<typename Seq::value_type>::value && std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 199
  193. #include "required_headers.hpp" template <typename Seq, typename Filter, typename = std::enable_if_t<

    std::is_integral<typename Seq::value_type>::value && std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 200 Hello .. 18 std::enable_if
  194. #include "required_headers.hpp" template <typename Seq, typename Filter, typename = std::enable_if_t<

    std::is_integral<typename Seq::value_type>::value && std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 201
  195. #include "required_headers.hpp" template <typename Seq, typename Filter, typename = std::enable_if_t<

    std::is_integral<typename Seq::value_type>::value && std::is_invocable<Filter, int>::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<char> 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.
  196. #include "required_headers.hpp" template <typename Seq, typename Filter, typename = std::enable_if_t<

    std::is_integral<typename Seq::value_type>::value && std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 203
  197. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <typename Seq, typename Filter, typename = std::enable_if_t< std::is_integral<typename Seq::value_type>::value && std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 204
  198. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <typename Seq, typename Filter, typename = std::enable_if_t< std::is_integral<typename Seq::value_type>::value && std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 205
  199. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <typename Seq, typename Filter> requires MySeqConcept<Seq>() && MyFilterConcept<Filter>() 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 206
  200. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <typename Seq, typename Filter> requires MySeqConcept<Seq>() && MyFilterConcept<Filter>() 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 207
  201. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <typename Seq, typename Filter> requires MySeqConcept<Seq>() && MyFilterConcept<Filter>() 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 208 Hello .. 19 concepts requires C++20?
  202. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <typename Seq, typename Filter> requires MySeqConcept<Seq>() && MyFilterConcept<Filter>() 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 209
  203. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <typename Seq, typename Filter> requires MySeqConcept<Seq>() && MyFilterConcept<Filter>() 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<char> 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.
  204. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <typename Seq, typename Filter> requires MySeqConcept<Seq>() && MyFilterConcept<Filter>() 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 211
  205. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <MySeqConcept Seq, MyFilterConcept Filter> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 212
  206. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <MySeqConcept Seq, MyFilterConcept Filter> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 213
  207. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <MySeqConcept Seq, MyFilterConcept Filter> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 214 Hello .. 20 concepts as template parameters C++20?
  208. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <MySeqConcept Seq, MyFilterConcept Filter> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 215
  209. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <MySeqConcept Seq, MyFilterConcept Filter> 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<char> 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.)
  210. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <MySeqConcept Seq, MyFilterConcept Filter> 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<char> 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.
  211. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <MySeqConcept Seq, MyFilterConcept Filter> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 218
  212. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <MySeqConcept Seq, MyFilterConcept Filter> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 219
  213. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } template <MySeqConcept Seq, MyFilterConcept Filter> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 220
  214. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } // template <MySeqConcept Seq, MyFilterConcept Filter> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 221
  215. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::value; } // template <MySeqConcept Seq, MyFilterConcept Filter> 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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 222
  216. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 223
  217. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 224
  218. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::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<char> 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.
  219. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 226
  220. #include "required_headers.hpp" template <typename Seq> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename Seq::value_type>::value; } template <typename Filter> concept bool MyFilterConcept() { return std::is_invocable<Filter, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 227
  221. #include "required_headers.hpp" template <typename T> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename T::value_type>::value; } template <typename T> concept bool MyFilterConcept() { return std::is_invocable<T, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 228
  222. #include "required_headers.hpp" template <typename T> concept bool MySeqConcept() { //

    TODO: also check that sequence is sortable return std::is_integral<typename T::value_type>::value; } template <typename T> concept bool MyFilterConcept() { return std::is_invocable<T, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 229
  223. #include "required_headers.hpp" template <typename T> concept bool Seq() { //

    TODO: also check that sequence is sortable return std::is_integral<typename T::value_type>::value; } template <typename T> concept bool Filter() { return std::is_invocable<T, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 230
  224. #include "required_headers.hpp" template <typename T> concept bool Seq() { //

    TODO: also check that sequence is sortable return std::is_integral<typename T::value_type>::value; } template <typename T> concept bool Filter() { return std::is_invocable<T, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 231
  225. #include "required_headers.hpp" template <typename T> concept bool Seq() { //

    TODO: also check that sequence is sortable return std::is_integral<typename T::value_type>::value; } template <typename T> concept bool Filter() { return std::is_invocable<T, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 232 Hello .. 21 concepts in function declaration C++26?
  226. #include "required_headers.hpp" template <typename T> concept bool Seq() { //

    TODO: also check that sequence is sortable return std::is_integral<typename T::value_type>::value; } template <typename T> concept bool Filter() { return std::is_invocable<T, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 233
  227. #include "required_headers.hpp" template <typename T> concept bool Seq() { //

    TODO: also check that sequence is sortable return std::is_integral<typename T::value_type>::value; } template <typename T> concept bool Filter() { return std::is_invocable<T, int>::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<char> 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.
  228. #include "required_headers.hpp" template <typename T> concept bool Seq() { //

    TODO: also check that sequence is sortable return std::is_integral<typename T::value_type>::value; } template <typename T> concept bool Filter() { return std::is_invocable<T, int>::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<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 235
  229. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (int)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 236
  230. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (int)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 237
  231. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (int)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 238
  232. #include "required_headers.hpp" void print(std::vector<char> seq, std::function<bool (int)> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq, [](char ch) { return !std::isalpha(ch); }); } 239
  233. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 240
  234. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 241 For efficiency, we might want to pass by reference.
  235. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 242
  236. #include "required_headers.hpp" void print(std::vector<char> & 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 243
  237. #include "required_headers.hpp" void print(std::vector<char> & 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> 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.
  238. #include "required_headers.hpp" void print(std::vector<char> & 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 245
  239. #include "required_headers.hpp" void print(std::vector<char> & 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 246 Hello .. 22 pass by lvalue reference
  240. #include "required_headers.hpp" void print(std::vector<char> & 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 247
  241. #include "required_headers.hpp" void print(std::vector<char> & 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> 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.
  242. #include "required_headers.hpp" void print(std::vector<char> & 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(seq); } 249
  243. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(std::move(seq)); } 250
  244. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(std::move(seq)); } 251
  245. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> 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.
  246. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(std::move(seq)); } 253
  247. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(std::move(seq)); } 254 Hello .. 23 pass by rvalue reference std::move
  248. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(std::move(seq)); } 255
  249. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> 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.
  250. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(std::move(seq)); } 257
  251. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(std::move(seq)); } 258
  252. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(std::move(seq)); } 259
  253. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(std::move(seq)); } 260
  254. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { std::vector<char> seq = greeting(); print(std::move(seq)); } 261
  255. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { std::vector<char> seq = greeting(); print(std::move(seq)); } 262
  256. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 263
  257. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 264
  258. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'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.
  259. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 266
  260. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 267 Hello .. 24 return value optimization and copy elision
  261. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 268
  262. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'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.
  263. #include "required_headers.hpp" void print(std::vector<char> && 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 270
  264. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 271
  265. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 272
  266. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 273 Hello .. 25 std::vector move constructor
  267. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 274
  268. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'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.
  269. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 276
  270. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } auto greeting() { return std::tuple<std::vector<char>,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42); } int main() { auto [str, answer] = greeting(); if (answer == 42) print(str); } 277
  271. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } auto greeting() { return std::tuple<std::vector<char>,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42); } int main() { auto [str, answer] = greeting(); if (answer == 42) print(str); } 278
  272. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } auto greeting() { return std::tuple<std::vector<char>,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42); } int main() { if (auto [str, answer] = greeting(); answer == 42) print(str); } 279
  273. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } auto greeting() { return std::tuple<std::vector<char>,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42); } int main() { if (auto [str, answer] = greeting(); answer == 42) print(str); } 280
  274. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } auto greeting() { return std::tuple<std::vector<char>,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
  275. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } auto greeting() { return std::tuple<std::vector<char>,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42); } int main() { if (auto [str, answer] = greeting(); answer == 42) print(str); } 282
  276. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } auto greeting() { return std::tuple<std::vector<char>,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42); } int main() { if (auto [str, answer] = greeting(); answer == 42) print(str); } 283 Now for something completely different!
  277. #include "required_headers.hpp" void print(std::vector<char> 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<char>::const_iterator(newend), std::putchar); } auto greeting() { return std::tuple<std::vector<char>,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42); } int main() { if (auto [str, answer] = greeting(); answer == 42) print(str); } 284
  278. #include "required_headers.hpp" std::size_t print(std::vector<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), std::putchar); return

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

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

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

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

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

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

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

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

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

    std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 294
  288. #include "required_headers.hpp" namespace my { void putchar(char ch) { std::cout

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

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

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

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

    << ch << std::flush; } } std::size_t print(std::vector<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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.
  293. #include "required_headers.hpp" namespace my { void putchar(char ch) { std::cout

    << ch << std::flush; } } std::size_t print(std::vector<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 300
  294. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 301
  295. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 302
  296. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 303
  297. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 304 H
  298. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 305 He
  299. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 306 Hel
  300. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 307 Hell
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 308 Hello
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 309 Hello .. 29 chrono and sleep_for
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 310
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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.
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 312
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; std::invoke(print, seq); } 313
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; auto n = std::invoke(print, seq); std::cout << n; } 314
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; auto n = std::invoke(print, seq); std::cout << n; } 315
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; auto n = std::invoke(print, seq); std::cout << n; } 316 Hello5 .. 30 std::invoke
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; auto n = std::invoke(print, seq); std::cout << n; } 317
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; auto n = std::invoke(print, seq); std::cout << n; } 319
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; auto f = std::async(print, seq); auto n = f.get(); std::cout << n; } 320
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; auto f = std::async(print, seq); auto n = f.get(); std::cout << n; } 321
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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.
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; auto f = std::async(print, seq); auto n = f.get(); std::cout << n; } 323
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; auto f = std::async(print, seq); auto n = f.get(); std::cout << n; } 324
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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.
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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.
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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...)
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } template <typename Func> void operator*(int n, Func f) { while (n--) f(); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } template <typename Func> void operator*(int n, Func f) { while (n--) f(); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } template <typename Func> void operator*(int n, Func f) { while (n--) f(); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } template <typename Func> void operator*(int n, Func f) { while (n--) f(); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } template <typename Func> void operator*(int n, Func f) { while (n--) f(); } int main() { std::vector<char> 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)
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } template <typename Func> void operator*(int n, Func f) { while (n--) f(); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } template <typename Func> void operator*(int n, Func f) { while (n--) f(); } int main() { std::vector<char> 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.
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } template <typename Func> void operator*(int n, Func f) { while (n--) f(); } int main() { std::vector<char> 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
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; auto f = std::async(std::launch::async, print, seq); auto n = f.get(); std::cout << n; } 351
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; auto f = std::async(std::launch::async, print, seq); auto n = f.get(); std::cout << n; } 352
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 353
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 354
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 355 Here we go, user-defined literals!
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 356
  350. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 357
  351. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 358
  352. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 359
  353. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 360
  354. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 361
  355. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 362 H
  356. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 363 He
  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(500_ms); std::cout << ch << std::flush; } } std::size_t print(std::vector<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 364 Hel
  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(500_ms); std::cout << ch << std::flush; } } std::size_t print(std::vector<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 365 Hell
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 366 Hello
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 367 Hello .. 35 user-defined literals (UDL)
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 368
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 369 The C++ standard library already comes with a handful of useful user-defined literals.
  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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 370
  364. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 371
  365. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 372
  366. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 373 Hello .. 36 std::chrono_literals
  367. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 374
  368. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 375
  369. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 376
  370. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 377
  371. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 378 Even nanoseconds.
  372. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 379 Even nanoseconds. Phew, this is hard to read...
  373. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 380
  374. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 381
  375. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 382
  376. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 383 Better?
  377. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 384
  378. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 385 Hello .. 37 digits separator
  379. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 386
  380. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 387 Now for something completely different...
  381. #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<char> seq) { std::for_each(std::crbegin(seq), std::crend(seq), my::putchar); return std::size(seq); } int main() { std::vector<char> seq{'o', 'l', 'l', 'e', 'H'}; print(seq); } 388
  382. #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
  383. #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
  384. #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
  385. #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
  386. #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...
  387. #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
  388. #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
  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::size_t len = ei - bi; std::string_view sv(&s[bi], len); std::for_each(&s[bi], &s[ei], std::putchar); } 396
  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::size_t len = ei - bi; std::string_view sv(&s[bi], len); std::for_each(std::cbegin(sv), std::cend(sv), std::putchar); } 397
  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::size_t len = ei - bi; std::string_view sv(&s[bi], len); std::for_each(std::cbegin(sv), std::cend(sv), std::putchar); } 398
  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::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.
  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::size_t len = ei - bi; std::string_view sv(&s[bi], len); std::for_each(std::cbegin(sv), std::cend(sv), std::putchar); } 400
  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::size_t len = ei - bi; std::string_view sv(&s[bi], len); std::for_each(std::cbegin(sv), std::cend(sv), std::putchar); } 401
  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); for (char c : sv) std::putchar(c); } 402
  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); for (char c : sv) std::putchar(c); } 403
  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); for (char c : sv) std::putchar(c); } 404 Hello .. 39 std::string_view range-for
  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); for (char c : sv) std::putchar(c); } 405
  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); for (char c : sv) std::putchar(c); } 406 The C++ standard library also comes with predefined string literals.
  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); for (char c : sv) std::putchar(c); } 407
  401. #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
  402. #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
  403. #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
  404. #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
  405. #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
  406. #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
  407. #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...
  408. #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
  409. #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
  410. #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
  411. #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
  412. #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
  413. #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.
  414. #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
  415. #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
  416. #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
  417. #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
  418. #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
  419. #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...
  420. #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
  421. #include <iostream> int main() { std::cout << "Hello\n"; } 429

    It is possible to print out "Hello" just like this.
  422. 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"
  423. 434

  424. #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<char> seq) { std::vector<std::future<void>> futures(std::size(seq)); for (char ch : seq) futures.emplace_back(std::async(my::putchar, ch, ch)); } int main() { std::vector<char> seq{'e', 'l', 'H', 'o', 'l'}; print(seq); } 436 Hello .. sleep sort