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

5fe162a4eca2d85e10faeb5bd33a7f7b?s=47 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.

5fe162a4eca2d85e10faeb5bd33a7f7b?s=128

Olve Maudal

September 25, 2018
Tweet

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); } 96
  97. #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.
  98. #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); } 98
  99. #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); } 99
  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); } 100
  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); } 101
  102. #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)
  103. #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); } 103
  104. #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); } 104
  105. #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
  106. #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.
  107. #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
  108. #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
  109. #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
  110. #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.
  111. #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
  112. #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
  113. #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
  114. #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.
  115. #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
  116. #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
  117. #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
  118. #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.
  119. #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
  120. #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
  121. #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
  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), 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
  123. #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
  124. #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
  125. #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
  126. #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
  127. #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
  128. #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
  129. #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
  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); } 130
  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); } 131
  132. #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
  133. #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
  134. #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
  135. #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
  136. #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.
  137. #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
  138. #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
  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), ::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
  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), ::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
  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'}; print(seq, ::ispunct); } 141
  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'}; print(seq, ::ispunct); } 142
  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'}; print(seq, ::ispunct); } 143 Hello .. 12 std::function
  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'}; print(seq, ::ispunct); } 144
  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'}; print(seq, ::ispunct); } 145 Now we can pass in quite advanced filters. Let us create an old-school function object (aka functor).
  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'}; print(seq, ::ispunct); } 146
  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, ::ispunct); } 147
  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, ::ispunct); } 148
  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); } 149
  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); } 150 Here we have a filter allowing just 4 letters.
  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); } 151 Notice, the key trick here is to overload the call operator.
  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'}); print(seq, myfilter); } 152
  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'}); print(seq, myfilter); } 153 Hello .. 13 function objects (aka functors)
  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'}); print(seq, myfilter); } 154
  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'}); print(seq, myfilter); } 155 We can also use lambda expressions to create function objects.
  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'}; 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
  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'}; 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
  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'}; 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
  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'}; //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
  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'}; //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
  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'}; //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.
  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'}; //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
  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 = [vc=std::set<char>{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); }; print(seq, myfilter); } 163
  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'}; auto myfilter = [vc=std::set<char>{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); }; print(seq, myfilter); } 164
  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'}; 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
  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'}; auto myfilter = [vc=std::set<char>{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); }; print(seq, myfilter); } 166
  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'}; 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.
  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'}; auto myfilter = [vc=std::set<char>{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); }; print(seq, myfilter); } 168
  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'}; auto myfilter = [](char ch) { return !std::isalpha(ch); }; print(seq, myfilter); } 169
  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'}; auto myfilter = [](char ch) { return !std::isalpha(ch); }; print(seq, myfilter); } 170
  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); }); } 171
  172. #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
  173. #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
  174. #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
  175. #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.
  176. #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
  177. #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
  178. #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
  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), 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
  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), 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
  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); }); } 181
  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); }); } 182
  183. #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.
  184. #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
  185. #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
  186. #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
  187. #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.
  188. #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
  189. #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
  190. #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
  191. #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
  192. #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
  193. #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
  194. #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.
  195. #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
  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) { 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
  197. #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
  198. #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
  199. #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
  200. #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
  201. #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
  202. #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.
  203. #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
  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, 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
  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 <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
  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 <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
  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 <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
  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 <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?
  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 <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
  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 <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.
  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 <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
  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 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
  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 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
  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(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?
  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(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
  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; } 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.)
  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; } 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.
  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; } 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
  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; } 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
  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; } 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
  221. #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
  222. #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
  223. #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
  224. #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
  225. #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.
  226. #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
  227. #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
  228. #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
  229. #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
  230. #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
  231. #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
  232. #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?
  233. #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
  234. #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.
  235. #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
  236. #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
  237. #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
  238. #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
  239. #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
  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); } 240
  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); } 241 For efficiency, we might want to pass by reference.
  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); } 242
  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(seq); } 243
  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(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.
  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(seq); } 245
  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(seq); } 246 Hello .. 22 pass by lvalue reference
  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(seq); } 247
  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(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.
  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(seq); } 249
  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)); } 250
  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)); } 251
  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); } 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.
  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); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(std::move(seq)); } 253
  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); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(std::move(seq)); } 254 Hello .. 23 pass by rvalue reference std::move
  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); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(std::move(seq)); } 255
  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); } 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.
  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); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(std::move(seq)); } 257
  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); } int main() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(std::move(seq)); } 258
  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() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(std::move(seq)); } 259
  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() { std::vector<char> seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; print(std::move(seq)); } 260
  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() { std::vector<char> seq = greeting(); print(std::move(seq)); } 261
  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() { std::vector<char> seq = greeting(); print(std::move(seq)); } 262
  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()); } 263
  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()); } 264
  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()); } 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.
  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()); } 266
  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()); } 267 Hello .. 24 return value optimization and copy elision
  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()); } 268
  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()); } 269 std::vector has a move constructor, so here pass by value is just moving elements if we give it an rvalue.
  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); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 270
  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); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 271
  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); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 272
  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); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 273 Hello .. 25 std::vector move constructor
  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); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 274
  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); } 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.
  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); } std::vector<char> greeting() { return std::vector<char>{'e', '&', '.', 'l', 'l', '{', 'H', 'o'}; } int main() { print(greeting()); } 276
  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() { auto [str, answer] = greeting(); if (answer == 42) print(str); } 277
  278. #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
  279. #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
  280. #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
  281. #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
  282. #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
  283. #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!
  284. #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
  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); } 285
  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); } 286
  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); } 287 Notice that the elements are in the wrong order.
  288. #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
  289. #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.
  290. #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
  291. #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
  292. #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
  293. #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.
  294. #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
  295. #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
  296. #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
  297. #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
  298. #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
  299. #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.
  300. #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
  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); } 301
  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); } 302
  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); } 303
  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); } 304 H
  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); } 305 He
  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'}; print(seq); } 306 Hel
  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'}; print(seq); } 307 Hell
  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'}; print(seq); } 308 Hello
  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'}; print(seq); } 309 Hello .. 29 chrono and sleep_for
  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'}; print(seq); } 310
  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'}; print(seq); } 311 We will soon show how to run code asynchronously. But first we show an alternative way to invoke a function.
  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'}; print(seq); } 312
  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'}; std::invoke(print, seq); } 313
  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 n = std::invoke(print, seq); std::cout << n; } 314
  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 n = std::invoke(print, seq); std::cout << n; } 315
  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 n = std::invoke(print, seq); std::cout << n; } 316 Hello5 .. 30 std::invoke
  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 n = std::invoke(print, seq); std::cout << n; } 317
  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 n = std::invoke(print, seq); std::cout << n; } 318 Now we can replace std::invoke with std::async
  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 n = std::invoke(print, seq); std::cout << n; } 319
  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); auto n = f.get(); std::cout << n; } 320
  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); auto n = f.get(); std::cout << n; } 321
  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); 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.
  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); auto n = f.get(); std::cout << n; } 323
  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(print, seq); auto n = f.get(); std::cout << n; } 324
  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(print, seq); for (int i = 10; i; --i) my::putchar('.'); auto n = f.get(); std::cout << n; } 325
  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(print, seq); for (int i = 10; i; --i) my::putchar('.'); auto n = f.get(); std::cout << n; } 326
  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(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
  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(print, seq); for (int i = 10; i; --i) my::putchar('.'); auto n = f.get(); std::cout << n; } 328
  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(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.
  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(print, seq); for (int i = 10; i; --i) my::putchar('.'); auto n = f.get(); std::cout << n; } 330
  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::deferred, print, seq); for (int i = 10; i; --i) my::putchar('.'); auto n = f.get(); std::cout << n; } 331
  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::deferred, print, seq); for (int i = 10; i; --i) my::putchar('.'); auto n = f.get(); std::cout << n; } 332
  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::deferred, print, seq); for (int i = 10; i; --i) my::putchar('.'); auto n = f.get(); std::cout << n; } 333 ..........Hello5 .. 32 deferred launch policy
  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::deferred, print, seq); for (int i = 10; i; --i) my::putchar('.'); auto n = f.get(); std::cout << n; } 334
  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::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.
  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); } 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
  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); } 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
  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); } 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
  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); } 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
  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); } 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
  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); } 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...)
  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); } 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
  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); for (int i = 10; i; --i) my::putchar('.'); auto n = f.get(); std::cout << n; } 343
  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); } 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
  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); } 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
  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); } 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
  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); } 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)
  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); } 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
  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); } 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.
  350. #include "required_headers.hpp" namespace my { void putchar(char ch) { std::this_thread::sleep_for(std::chrono::milliseconds(500));

    std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  351. #include "required_headers.hpp" namespace my { void putchar(char ch) { std::this_thread::sleep_for(std::chrono::milliseconds(500));

    std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  352. #include "required_headers.hpp" namespace my { void putchar(char ch) { std::this_thread::sleep_for(std::chrono::milliseconds(500));

    std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  353. #include "required_headers.hpp" namespace my { void putchar(char ch) { std::this_thread::sleep_for(std::chrono::milliseconds(500));

    std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  354. #include "required_headers.hpp" namespace my { void putchar(char ch) { std::this_thread::sleep_for(std::chrono::milliseconds(500));

    std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  355. #include "required_headers.hpp" namespace my { void putchar(char ch) { std::this_thread::sleep_for(std::chrono::milliseconds(500));

    std::cout << ch << std::flush; } } std::size_t print(std::vector<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!
  356. #include "required_headers.hpp" namespace my { void putchar(char ch) { std::this_thread::sleep_for(std::chrono::milliseconds(500));

    std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  357. #include "required_headers.hpp" auto operator"" _ms(unsigned long long n) { return

    std::chrono::milliseconds(n); } namespace my { void putchar(char ch) { std::this_thread::sleep_for(std::chrono::milliseconds(500)); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  358. #include "required_headers.hpp" auto operator"" _ms(unsigned long long n) { return

    std::chrono::milliseconds(n); } namespace my { void putchar(char ch) { std::this_thread::sleep_for(std::chrono::milliseconds(500)); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  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); } 359
  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); } 360
  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); } 361
  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); } 362 H
  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); } 363 He
  364. #include "required_headers.hpp" auto operator"" _ms(unsigned long long n) { return

    std::chrono::milliseconds(n); } namespace my { void putchar(char ch) { std::this_thread::sleep_for(500_ms); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  365. #include "required_headers.hpp" auto operator"" _ms(unsigned long long n) { return

    std::chrono::milliseconds(n); } namespace my { void putchar(char ch) { std::this_thread::sleep_for(500_ms); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  366. #include "required_headers.hpp" auto operator"" _ms(unsigned long long n) { return

    std::chrono::milliseconds(n); } namespace my { void putchar(char ch) { std::this_thread::sleep_for(500_ms); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  367. #include "required_headers.hpp" auto operator"" _ms(unsigned long long n) { return

    std::chrono::milliseconds(n); } namespace my { void putchar(char ch) { std::this_thread::sleep_for(500_ms); std::cout << ch << std::flush; } } std::size_t print(std::vector<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)
  368. #include "required_headers.hpp" auto operator"" _ms(unsigned long long n) { return

    std::chrono::milliseconds(n); } namespace my { void putchar(char ch) { std::this_thread::sleep_for(500_ms); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  369. #include "required_headers.hpp" auto operator"" _ms(unsigned long long n) { return

    std::chrono::milliseconds(n); } namespace my { void putchar(char ch) { std::this_thread::sleep_for(500_ms); std::cout << ch << std::flush; } } std::size_t print(std::vector<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.
  370. #include "required_headers.hpp" auto operator"" _ms(unsigned long long n) { return

    std::chrono::milliseconds(n); } namespace my { void putchar(char ch) { std::this_thread::sleep_for(500_ms); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  371. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500ms); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  372. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500ms); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  373. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500ms); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  374. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500ms); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  375. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500ms); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  376. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500000000ns); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  377. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500000000ns); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  378. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500000000ns); std::cout << ch << std::flush; } } std::size_t print(std::vector<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.
  379. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500000000ns); std::cout << ch << std::flush; } } std::size_t print(std::vector<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...
  380. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500000000ns); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  381. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500000000ns); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  382. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500'000'000ns); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  383. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500'000'000ns); std::cout << ch << std::flush; } } std::size_t print(std::vector<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?
  384. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500'000'000ns); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  385. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500'000'000ns); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  386. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500'000'000ns); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  387. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500'000'000ns); std::cout << ch << std::flush; } } std::size_t print(std::vector<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...
  388. #include "required_headers.hpp" using namespace std::chrono_literals; namespace my { void putchar(char

    ch) { std::this_thread::sleep_for(500'000'000ns); std::cout << ch << std::flush; } } std::size_t print(std::vector<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
  389. #include "required_headers.hpp" int main() { std::string s = "................Hello.........."; std::size_t

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    s = "................Hello.........."sv; constexpr std::size_t bi = std::min(s.find_first_not_of('.'), std::size(s)); constexpr std::size_t ei = std::min(s.find_first_of('.',bi), std::size(s)); constexpr std::size_t len = ei - bi; constexpr std::string_view sv(&s[bi], len); for (char c : sv) std::putchar(c); } 427
  428. #include <iostream> int main() { std::cout << "Hello\n"; } 428

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

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

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

    Hello .. 42 just "Hello"
  432. 432 !

  433. 433 1. iterators 2. std::cbegin() / std::cend() 3. type deduction

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

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

  436. #include "required_headers.hpp" namespace my { void putchar(char ch, long delay)

    { std::this_thread::sleep_for(std::chrono::milliseconds(delay)); std::cout << ch << std::flush; } } void print(std::vector<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