Share
Embed
42 silly ways to say "Hello" in modern C++ (Sep 2018)
The title says "silly", but this is really a serious attempt to compress essential stuff from a 2 day course on modern C++ into a brief presentation.
Olve Maudal
September 25, 2018
Transcript
436 slides
-
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 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! -
#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 -
#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. -
#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. -
#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. -
#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. -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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... -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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() -
#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 -
#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. -
#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 -
#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... -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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) -
#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 -
#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 -
#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... -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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... -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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... -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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. -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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) -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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). -
#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 -
#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 -
#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 -
#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 -
#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. -
#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. -
#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 -
#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) -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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? -
#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 -
#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. -
#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 -
#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 -
#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 -
#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? -
#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 -
#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.) -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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? -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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! -
#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 -
#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 -
#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 -
#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. -
#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 -
#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. -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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...) -
#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 -
#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 -
#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 -
#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 -
#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 -
#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) -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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! -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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) -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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... -
#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 -
#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 -
#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 -
#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? -
#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 -
#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 -
#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 -
#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... -
#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 -
#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 -
#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 -
#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 -
#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 -
#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... -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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 -
#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... -
#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 -
#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 -
#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 -
#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 -
#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 -
#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. -
#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 -
#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 -
#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 -
#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 -
#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 -
#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... -
#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 -
#include <iostream> int main() { std::cout << "Hello\n"; } 429
It is possible to print out "Hello" just like this. -
#include <iostream> int main() { std::cout << "Hello\n"; } 431
Hello .. 42 just "Hello" -
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" -
#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