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.
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
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
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
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
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
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
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
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
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
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
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
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 & seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::array seq{'H', 'e', 'l', 'l', 'o'};
print(seq);
}
81
#include "required_headers.hpp"
void print(const std::array & seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::array seq{'H', 'e', 'l', 'l', 'o'};
print(seq);
}
82
#include "required_headers.hpp"
void print(const std::array & seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::array seq{'H', 'e', 'l', 'l', 'o'};
print(seq);
}
83
#include "required_headers.hpp"
void print(const std::array & seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::array seq{'H', 'e', 'l', 'l', 'o'};
print(seq);
}
84
#include "required_headers.hpp"
void print(const std::array & seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::array seq{'H', 'e', 'l', 'l', 'o'};
print(seq);
}
85
Hello
..
7
std::array
#include "required_headers.hpp"
void print(const std::array & seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::array seq{'H', 'e', 'l', 'l', 'o'};
print(seq);
}
86
#include "required_headers.hpp"
void print(const std::array & seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::array seq{'H', 'e', 'l', 'l', 'o'};
print(seq);
}
87
... and std::vector
#include "required_headers.hpp"
void print(const std::vector & seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'H', 'e', 'l', 'l', 'o'};
print(seq);
}
88
#include "required_headers.hpp"
void print(const std::vector & seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'H', 'e', 'l', 'l', 'o'};
print(seq);
}
89
#include "required_headers.hpp"
void print(const std::vector & seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'H', 'e', 'l', 'l', 'o'};
print(seq);
}
90
Hello
..
8
std::vector
#include "required_headers.hpp"
void print(const std::vector & seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'H', 'e', 'l', 'l', 'o'};
print(seq);
}
91
#include "required_headers.hpp"
void print(const std::vector & seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'H', 'e', 'l', 'l', 'o'};
print(seq);
}
92
#include "required_headers.hpp"
void print(const std::vector & seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', 'l', 'l', 'H', 'o'};
print(seq);
}
93
#include "required_headers.hpp"
void print(const std::vector & seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', 'l', 'l', 'H', 'o'};
print(seq);
}
94
Perhaps we need to rearrange the elements
before printing out.
#include "required_headers.hpp"
void print(const std::vector & seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', 'l', 'l', 'H', 'o'};
print(seq);
}
95
Then we might want to pass by value so that
we get a copy of the container.
#include "required_headers.hpp"
void print(std::vector seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', 'l', 'l', 'H', 'o'};
print(seq);
}
96
#include "required_headers.hpp"
void print(std::vector seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', 'l', 'l', 'H', 'o'};
print(seq);
}
97
And now we can sort the elements.
#include "required_headers.hpp"
void print(std::vector seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', 'l', 'l', 'H', 'o'};
print(seq);
}
98
#include "required_headers.hpp"
void print(std::vector seq)
{
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', 'l', 'l', 'H', 'o'};
print(seq);
}
99
#include "required_headers.hpp"
void print(std::vector seq)
{
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', 'l', 'l', 'H', 'o'};
print(seq);
}
100
#include "required_headers.hpp"
void print(std::vector seq)
{
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', 'l', 'l', 'H', 'o'};
print(seq);
}
101
#include "required_headers.hpp"
void print(std::vector seq)
{
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', 'l', 'l', 'H', 'o'};
print(seq);
}
102
Hello
..
9
std::sort
pass by value (copy)
#include "required_headers.hpp"
void print(std::vector seq)
{
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', 'l', 'l', 'H', 'o'};
print(seq);
}
103
#include "required_headers.hpp"
void print(std::vector seq)
{
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', 'l', 'l', 'H', 'o'};
print(seq);
}
104
#include "required_headers.hpp"
void print(std::vector seq)
{
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
105
#include "required_headers.hpp"
void print(std::vector seq)
{
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
106
Here we have some superfluous punctuation
characters that needs to be filtered out.
#include "required_headers.hpp"
void print(std::vector seq)
{
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
107
#include "required_headers.hpp"
void print(std::vector seq)
{
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
108
#include "required_headers.hpp"
void print(std::vector seq)
{
std::sort(std::begin(seq), std::end(seq));
seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
109
#include "required_headers.hpp"
void print(std::vector seq)
{
std::sort(std::begin(seq), std::end(seq));
seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
110
We apply the erase-remove idiom with
ispunct as a predicate.
#include "required_headers.hpp"
void print(std::vector seq)
{
std::sort(std::begin(seq), std::end(seq));
seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
111
#include "required_headers.hpp"
void print(std::vector seq)
{
std::sort(std::begin(seq), std::end(seq));
seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
112
Hello
..
10
erase-remove idiom
#include "required_headers.hpp"
void print(std::vector seq)
{
std::sort(std::begin(seq), std::end(seq));
seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
113
#include "required_headers.hpp"
void print(std::vector seq)
{
std::sort(std::begin(seq), std::end(seq));
seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
114
At this abstraction level it is easy to discover
optimization opportunities.
Here, it looks like we should filter out the
elements first and *then* sort the container.
#include "required_headers.hpp"
void print(std::vector seq)
{
std::sort(std::begin(seq), std::end(seq));
seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
115
#include "required_headers.hpp"
void print(std::vector seq)
{
seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
116
#include "required_headers.hpp"
void print(std::vector seq)
{
seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
117
#include "required_headers.hpp"
void print(std::vector seq)
{
seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
118
Another, now, obvious optimization is to let
sort and for_each work on the
subsequence after remove_if, making the
erase step obsolete.
#include "required_headers.hpp"
void print(std::vector seq)
{
seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
119
#include "required_headers.hpp"
void print(std::vector seq)
{
seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
120
#include "required_headers.hpp"
void print(std::vector seq)
{
seq.erase(std::remove_if(std::begin(seq), std::end(seq), ::ispunct), std::end(seq));
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
121
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
seq.erase(newend , std::end(seq));
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
122
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
seq.erase(newend , std::end(seq));
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
123
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
seq.erase(newend, std::end(seq));
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
124
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
seq.erase(newend, std::end(seq));
std::sort(std::begin(seq), std::end(seq));
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
125
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
seq.erase(newend, std::end(seq));
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
126
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
seq.erase(newend, std::end(seq));
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::cend(seq), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
127
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
seq.erase(newend, std::end(seq));
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
128
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
seq.erase(newend, std::end(seq));
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
129
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
130
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
131
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
132
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
133
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
134
Hello
..
11
algorithms and high level optimization
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
135
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
136
As well as values, you can also pass function
objects.
Now we will let the caller provide the
filter predicate.
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
137
#include "required_headers.hpp"
void print(std::vector seq )
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq );
}
138
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, ::ispunct);
}
139
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), ::ispunct);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, ::ispunct);
}
140
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, ::ispunct);
}
141
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, ::ispunct);
}
142
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, ::ispunct);
}
143
Hello
..
12
std::function
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, ::ispunct);
}
144
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, ::ispunct);
}
145
Now we can pass in quite advanced filters.
Let us create an old-school function object
(aka functor).
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, ::ispunct);
}
146
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
struct MyFilter {
MyFilter(std::set validchars) : validchars_(validchars) {}
bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
std::set validchars_;
} myfilter({'h','e','l','o'});
print(seq, ::ispunct);
}
147
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
struct MyFilter {
MyFilter(std::set validchars) : validchars_(validchars) {}
bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
std::set validchars_;
} myfilter({'h','e','l','o'});
print(seq, ::ispunct);
}
148
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
struct MyFilter {
MyFilter(std::set validchars) : validchars_(validchars) {}
bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
std::set validchars_;
} myfilter({'h','e','l','o'});
print(seq, myfilter);
}
149
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
struct MyFilter {
MyFilter(std::set validchars) : validchars_(validchars) {}
bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
std::set validchars_;
} myfilter({'h','e','l','o'});
print(seq, myfilter);
}
150
Here we have a filter allowing just 4 letters.
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
struct MyFilter {
MyFilter(std::set validchars) : validchars_(validchars) {}
bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
std::set validchars_;
} myfilter({'h','e','l','o'});
print(seq, myfilter);
}
151
Notice, the key trick here is to overload the
call operator.
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
struct MyFilter {
MyFilter(std::set validchars) : validchars_(validchars) {}
bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
std::set validchars_;
} myfilter({'h','e','l','o'});
print(seq, myfilter);
}
152
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
struct MyFilter {
MyFilter(std::set validchars) : validchars_(validchars) {}
bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
std::set validchars_;
} myfilter({'h','e','l','o'});
print(seq, myfilter);
}
153
Hello
..
13
function objects (aka functors)
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
struct MyFilter {
MyFilter(std::set validchars) : validchars_(validchars) {}
bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
std::set validchars_;
} myfilter({'h','e','l','o'});
print(seq, myfilter);
}
154
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
struct MyFilter {
MyFilter(std::set validchars) : validchars_(validchars) {}
bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
std::set validchars_;
} myfilter({'h','e','l','o'});
print(seq, myfilter);
}
155
We can also use lambda expressions to
create function objects.
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
struct MyFilter {
MyFilter(std::set validchars) : validchars_(validchars) {}
bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
std::set validchars_;
} myfilter({'h','e','l','o'});
print(seq, myfilter);
}
156
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
struct MyFilter {
MyFilter(std::set validchars) : validchars_(validchars) {}
bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
std::set validchars_;
} myfilter({'h','e','l','o'});
print(seq, myfilter);
}
157
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
struct MyFilter {
MyFilter(std::set validchars) : validchars_(validchars) {}
bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
std::set validchars_;
} myfilter({'h','e','l','o'});
print(seq, myfilter);
}
158
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
//struct MyFilter {
// MyFilter(std::set validchars) : validchars_(validchars) {}
// bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
// std::set validchars_;
//} myfilter({'h','e','l','o'});
auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
print(seq, myfilter);
}
159
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
//struct MyFilter {
// MyFilter(std::set validchars) : validchars_(validchars) {}
// bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
// std::set validchars_;
//} myfilter({'h','e','l','o'});
auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
print(seq, myfilter);
}
160
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
//struct MyFilter {
// MyFilter(std::set validchars) : validchars_(validchars) {}
// bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
// std::set validchars_;
//} myfilter({'h','e','l','o'});
auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
print(seq, myfilter);
}
161
The lambda is equivalent to our old-school
functor.
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
//struct MyFilter {
// MyFilter(std::set validchars) : validchars_(validchars) {}
// bool operator()(char ch) const { return validchars_.find(std::tolower(ch)) == validchars_.end(); }
// std::set validchars_;
//} myfilter({'h','e','l','o'});
auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
print(seq, myfilter);
}
162
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
print(seq, myfilter);
}
163
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
print(seq, myfilter);
}
164
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
print(seq, myfilter);
}
165
Hello
..
14
lamda expression and generalized lambda capture
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
print(seq, myfilter);
}
166
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
print(seq, myfilter);
}
167
Lambdas are often used as simple wrappers
for existing functions.
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
auto myfilter = [vc=std::set{'h','e','l','o'}](char ch) { return vc.find(std::tolower(ch)) == vc.end(); };
print(seq, myfilter);
}
168
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
auto myfilter = [](char ch) { return !std::isalpha(ch); };
print(seq, myfilter);
}
169
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
auto myfilter = [](char ch) { return !std::isalpha(ch); };
print(seq, myfilter);
}
170
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
171
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
172
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
173
Hello
..
15
wrap functions with lambda expressions
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
174
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
175
Let us rewrite print into
something more generic.
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
176
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
177
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
178
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
179
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
180
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
181
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
182
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
183
typename is needed here to help the compiler
to look for a type, instead of a value.
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
184
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
185
Hello
..
16
function template and dependent names
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
186
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
187
Generic code is nice, but often you will
need to specify certain requirements for
the template arguments. Types are
known at compile time, so we can use
type traits and static assert to reason
about template arguments.
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
188
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
189
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
static_assert(std::is_integral::value);
static_assert(std::is_invocable::value);
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
190
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
static_assert(std::is_integral::value);
static_assert(std::is_invocable::value);
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
191
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
static_assert(std::is_integral::value);
static_assert(std::is_invocable::value);
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
192
Hello
..
17
type traits
static assert
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
static_assert(std::is_integral::value);
static_assert(std::is_invocable::value);
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
193
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
static_assert(std::is_integral::value);
static_assert(std::is_invocable::value);
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
194
With enable_if we can take this idea
further and tell the compiler that if certain
requirements are not met, then a particular
template should not even be considered for
instantiation.
#include "required_headers.hpp"
template
void print(Seq seq, Filter filter)
{
static_assert(std::is_integral::value);
static_assert(std::is_invocable::value);
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
195
#include "required_headers.hpp"
template typename = std::enable_if_t<
std::is_integral::value &&
std::is_invocable::value> >
void print(Seq seq, Filter filter)
{
static_assert(std::is_integral::value);
static_assert(std::is_invocable::value);
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
196
#include "required_headers.hpp"
template typename = std::enable_if_t<
std::is_integral::value &&
std::is_invocable::value> >
void print(Seq seq, Filter filter)
{
static_assert(std::is_integral::value);
static_assert(std::is_invocable::value);
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
197
#include "required_headers.hpp"
template typename = std::enable_if_t<
std::is_integral::value &&
std::is_invocable::value> >
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
198
#include "required_headers.hpp"
template typename = std::enable_if_t<
std::is_integral::value &&
std::is_invocable::value> >
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
199
#include "required_headers.hpp"
template typename = std::enable_if_t<
std::is_integral::value &&
std::is_invocable::value> >
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
200
Hello
..
18
std::enable_if
#include "required_headers.hpp"
template typename = std::enable_if_t<
std::is_integral::value &&
std::is_invocable::value> >
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
201
#include "required_headers.hpp"
template typename = std::enable_if_t<
std::is_integral::value &&
std::is_invocable::value> >
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
202
C++20 will probably get Concepts, here is
approximately how it is supposed to work.
#include "required_headers.hpp"
template typename = std::enable_if_t<
std::is_integral::value &&
std::is_invocable::value> >
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
203
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template typename = std::enable_if_t<
std::is_integral::value &&
std::is_invocable::value> >
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
204
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template typename = std::enable_if_t<
std::is_integral::value &&
std::is_invocable::value> >
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
205
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template requires MySeqConcept() && MyFilterConcept()
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
206
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template requires MySeqConcept() && MyFilterConcept()
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
207
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template requires MySeqConcept() && MyFilterConcept()
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
208
Hello
..
19
concepts
requires
C++20?
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template requires MySeqConcept() && MyFilterConcept()
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
209
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template requires MySeqConcept() && MyFilterConcept()
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
210
concepts can be used instead of the keyword
typename in the template parameter list.
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template requires MySeqConcept() && MyFilterConcept()
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
211
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
212
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
213
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
214
Hello
..
20
concepts as template parameters
C++20?
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
215
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
216
I am now going to show something that probably will not make
it into C++20, and maybe never... However, with the current
version of gcc (8.2.0) it is possible to play with the idea of
using concepts instead of types in a function declaration. (The
effect is that you are really declaring a template.)
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
217
First I need to make a small change in the
iterator pair for the for_each since the Seq
type will soon be replaced by a concept.
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename Seq::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
218
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
219
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
template
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
220
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
// template
void print(MySeqConcept seq, MyFilterConcept filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
221
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
// template
void print(MySeqConcept seq, MyFilterConcept filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
222
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
void print(MySeqConcept seq, MyFilterConcept filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
223
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
void print(MySeqConcept seq, MyFilterConcept filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
224
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
void print(MySeqConcept seq, MyFilterConcept filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
225
Now that we are using the concept names in
the function declaration, we can go further
and rename them.
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
void print(MySeqConcept seq, MyFilterConcept filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
226
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
void print(MySeqConcept seq, MyFilterConcept filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
227
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
void print(MySeqConcept seq, MyFilterConcept filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
228
#include "required_headers.hpp"
template
concept bool MySeqConcept() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool MyFilterConcept() {
return std::is_invocable::value;
}
void print(MySeqConcept seq, MyFilterConcept filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
229
#include "required_headers.hpp"
template
concept bool Seq() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool Filter() {
return std::is_invocable::value;
}
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
230
#include "required_headers.hpp"
template
concept bool Seq() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool Filter() {
return std::is_invocable::value;
}
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
231
#include "required_headers.hpp"
template
concept bool Seq() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool Filter() {
return std::is_invocable::value;
}
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
232
Hello
..
21
concepts in function declaration
C++26?
#include "required_headers.hpp"
template
concept bool Seq() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool Filter() {
return std::is_invocable::value;
}
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
233
#include "required_headers.hpp"
template
concept bool Seq() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool Filter() {
return std::is_invocable::value;
}
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
234
Enough templates and concepts for now.
Let's simplify the code.
#include "required_headers.hpp"
template
concept bool Seq() {
// TODO: also check that sequence is sortable
return std::is_integral::value;
}
template
concept bool Filter() {
return std::is_invocable::value;
}
void print(Seq seq, Filter filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), typename decltype(seq)::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
235
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
236
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), filter);
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
237
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
238
#include "required_headers.hpp"
void print(std::vector seq, std::function filter)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq, [](char ch) { return !std::isalpha(ch); });
}
239
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
240
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
241
For efficiency, we might want to
pass by reference.
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
242
#include "required_headers.hpp"
void print(std::vector & seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
243
#include "required_headers.hpp"
void print(std::vector & seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
244
The key thing here is the & to avoid a copy
operation. We pass the sequence by a so
called lvalue reference. Since we are not
using the sequence after the call to print, this
might be an acceptable solution.
#include "required_headers.hpp"
void print(std::vector & seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
245
#include "required_headers.hpp"
void print(std::vector & seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
246
Hello
..
22
pass by lvalue reference
#include "required_headers.hpp"
void print(std::vector & seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
247
#include "required_headers.hpp"
void print(std::vector & seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
248
It would be nice to express ownership when
passing references like this. Who owns the
content of the object? With rvalue references
and move semantics you can in our example
express transfer of ownership with && and a
std::move.
#include "required_headers.hpp"
void print(std::vector & seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(seq);
}
249
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(std::move(seq));
}
250
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(std::move(seq));
}
251
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(std::move(seq));
}
252
It is important to realize that std::move is
just a cast from lvalue to rvalue.
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(std::move(seq));
}
253
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(std::move(seq));
}
254
Hello
..
23
pass by rvalue reference
std::move
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(std::move(seq));
}
255
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(std::move(seq));
}
256
Now we will show how rvalue references can
bind to objects without a name, eg a return
value from a function.
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(std::move(seq));
}
257
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(std::move(seq));
}
258
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(std::move(seq));
}
259
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
std::vector seq{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
print(std::move(seq));
}
260
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
std::vector seq = greeting();
print(std::move(seq));
}
261
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
std::vector seq = greeting();
print(std::move(seq));
}
262
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
print(greeting());
}
263
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
print(greeting());
}
264
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
print(greeting());
}
265
Due to return value optimization, copy
elision, rvalues and move semantics,
nothing will be copied here. All the elements
(and the ownership) are just moved into the
print function.
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
print(greeting());
}
266
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
print(greeting());
}
267
Hello
..
24
return value optimization and copy elision
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
print(greeting());
}
268
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
print(greeting());
}
269
std::vector has a move constructor, so
here pass by value is just moving elements if
we give it an rvalue.
#include "required_headers.hpp"
void print(std::vector && seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
print(greeting());
}
270
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
print(greeting());
}
271
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
print(greeting());
}
272
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
print(greeting());
}
273
Hello
..
25
std::vector move constructor
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
print(greeting());
}
274
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
print(greeting());
}
275
When planning this presentation, I promised
myself that I would show structural binding
and if statement with initialization. Although
a small detour, this is the time to show it.
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
std::vector greeting()
{
return std::vector{'e', '&', '.', 'l', 'l', '{', 'H', 'o'};
}
int main()
{
print(greeting());
}
276
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
auto greeting()
{
return std::tuple,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42);
}
int main()
{
auto [str, answer] = greeting();
if (answer == 42)
print(str);
}
277
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
auto greeting()
{
return std::tuple,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42);
}
int main()
{
auto [str, answer] = greeting();
if (answer == 42)
print(str);
}
278
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
auto greeting()
{
return std::tuple,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42);
}
int main()
{
if (auto [str, answer] = greeting(); answer == 42)
print(str);
}
279
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
auto greeting()
{
return std::tuple,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42);
}
int main()
{
if (auto [str, answer] = greeting(); answer == 42)
print(str);
}
280
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
auto greeting()
{
return std::tuple,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42);
}
int main()
{
if (auto [str, answer] = greeting(); answer == 42)
print(str);
}
281
Hello
..
26
if statement with initializer
std::tuple
structural binding
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
auto greeting()
{
return std::tuple,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42);
}
int main()
{
if (auto [str, answer] = greeting(); answer == 42)
print(str);
}
282
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
auto greeting()
{
return std::tuple,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42);
}
int main()
{
if (auto [str, answer] = greeting(); answer == 42)
print(str);
}
283
Now for something completely different!
#include "required_headers.hpp"
void print(std::vector seq)
{
auto newend = std::remove_if(std::begin(seq), std::end(seq), [](char ch) { return !std::isalpha(ch); });
std::sort(std::begin(seq), newend);
std::for_each(std::cbegin(seq), std::vector::const_iterator(newend), std::putchar);
}
auto greeting()
{
return std::tuple,int>({'e', '&', '.', 'l', 'l', '{', 'H', 'o'}, 42);
}
int main()
{
if (auto [str, answer] = greeting(); answer == 42)
print(str);
}
284
#include "required_headers.hpp"
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
285
#include "required_headers.hpp"
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
286
#include "required_headers.hpp"
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
287
Notice that the elements are in the wrong order.
#include "required_headers.hpp"
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
288
#include "required_headers.hpp"
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
289
No problem, just apply reverse iterators to get it right.
#include "required_headers.hpp"
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
290
#include "required_headers.hpp"
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
291
Hello
..
27
reverse iterators
#include "required_headers.hpp"
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
292
#include "required_headers.hpp"
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
293
Let's write our very own putchar and put it in
our very own namespace.
#include "required_headers.hpp"
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), std::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
294
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
295
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
296
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
297
Hello
..
28
namespace and std::flush
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
298
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
299
Let's introduce a type writer effect by adding
a small pause before printing each character.
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
300
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
301
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
302
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
303
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
304
H
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
305
He
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
306
Hel
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
307
Hell
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
308
Hello
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
309
Hello
..
29
chrono and sleep_for
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
310
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
311
We will soon show how to run code
asynchronously. But first we show an
alternative way to invoke a function.
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
312
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
std::invoke(print, seq);
}
313
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto n = std::invoke(print, seq);
std::cout << n;
}
314
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto n = std::invoke(print, seq);
std::cout << n;
}
315
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto n = std::invoke(print, seq);
std::cout << n;
}
316
Hello5
..
30
std::invoke
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto n = std::invoke(print, seq);
std::cout << n;
}
317
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto n = std::invoke(print, seq);
std::cout << n;
}
318
Now we can replace std::invoke with
std::async
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto n = std::invoke(print, seq);
std::cout << n;
}
319
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(print, seq);
auto n = f.get();
std::cout << n;
}
320
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(print, seq);
auto n = f.get();
std::cout << n;
}
321
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(print, seq);
auto n = f.get();
std::cout << n;
}
322
std::async returns a future that holds a
value that we can retrieve later. Notice how
invoking and getting the result is now two
separate statements, this allow us to
something while it is executing.
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(print, seq);
auto n = f.get();
std::cout << n;
}
323
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(print, seq);
auto n = f.get();
std::cout << n;
}
324
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
325
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
326
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
327
.H.el.l..o.....5
..
31
this what I often get on my
machine...
std::async
promise and future
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
328
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
329
The default launch policy depends on your
compiler/runtime. By explicitly specify the
launch policy you can for example defer
execution until you call the get() function.
This can be useful, in particular when
debugging.
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
330
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::deferred, print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
331
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::deferred, print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
332
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::deferred, print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
333
..........Hello5
..
32
deferred launch policy
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::deferred, print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
334
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::deferred, print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
335
Or you can specify that you want threads to
be created and started.
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::deferred, print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
336
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::async, print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
337
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::async, print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
338
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::async, print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
339
.H.el.l..o.....5
..
33
async launch policy
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::async, print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
340
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::async, print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
341
Ok, I just can not resist... let's have some fun
with overloading the multiplication operator
and create a repeat function. (Don't do this in
your codebase...)
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::async, print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
342
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
template
void operator*(int n, Func f)
{
while (n--)
f();
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::async, print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
343
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
template
void operator*(int n, Func f)
{
while (n--)
f();
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::async, print, seq);
for (int i = 10; i; --i)
my::putchar('.');
auto n = f.get();
std::cout << n;
}
344
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
template
void operator*(int n, Func f)
{
while (n--)
f();
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::async, print, seq);
10 * []{ my::putchar('.'); };
auto n = f.get();
std::cout << n;
}
345
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
template
void operator*(int n, Func f)
{
while (n--)
f();
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::async, print, seq);
10 * []{ my::putchar('.'); };
auto n = f.get();
std::cout << n;
}
346
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
template
void operator*(int n, Func f)
{
while (n--)
f();
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::async, print, seq);
10 * []{ my::putchar('.'); };
auto n = f.get();
std::cout << n;
}
347
.H.el.l..o.....5
..
34
silly operator overload (don't do this)
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
template
void operator*(int n, Func f)
{
while (n--)
f();
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::async, print, seq);
10 * []{ my::putchar('.'); };
auto n = f.get();
std::cout << n;
}
348
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
template
void operator*(int n, Func f)
{
while (n--)
f();
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::async, print, seq);
10 * []{ my::putchar('.'); };
auto n = f.get();
std::cout << n;
}
349
I am now going to show user-defined literals,
but first we clean up the code.
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
template
void operator*(int n, Func f)
{
while (n--)
f();
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::async, print, seq);
10 * []{ my::putchar('.'); };
auto n = f.get();
std::cout << n;
}
350
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::async, print, seq);
auto n = f.get();
std::cout << n;
}
351
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
auto f = std::async(std::launch::async, print, seq);
auto n = f.get();
std::cout << n;
}
352
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
353
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
354
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
355
Here we go, user-defined literals!
#include "required_headers.hpp"
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
356
#include "required_headers.hpp"
auto operator"" _ms(unsigned long long n)
{
return std::chrono::milliseconds(n);
}
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
357
#include "required_headers.hpp"
auto operator"" _ms(unsigned long long n)
{
return std::chrono::milliseconds(n);
}
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
358
#include "required_headers.hpp"
auto operator"" _ms(unsigned long long n)
{
return std::chrono::milliseconds(n);
}
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500_ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
359
#include "required_headers.hpp"
auto operator"" _ms(unsigned long long n)
{
return std::chrono::milliseconds(n);
}
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500_ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
360
#include "required_headers.hpp"
auto operator"" _ms(unsigned long long n)
{
return std::chrono::milliseconds(n);
}
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500_ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
361
#include "required_headers.hpp"
auto operator"" _ms(unsigned long long n)
{
return std::chrono::milliseconds(n);
}
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500_ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
362
H
#include "required_headers.hpp"
auto operator"" _ms(unsigned long long n)
{
return std::chrono::milliseconds(n);
}
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500_ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
363
He
#include "required_headers.hpp"
auto operator"" _ms(unsigned long long n)
{
return std::chrono::milliseconds(n);
}
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500_ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
364
Hel
#include "required_headers.hpp"
auto operator"" _ms(unsigned long long n)
{
return std::chrono::milliseconds(n);
}
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500_ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
365
Hell
#include "required_headers.hpp"
auto operator"" _ms(unsigned long long n)
{
return std::chrono::milliseconds(n);
}
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500_ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
366
Hello
#include "required_headers.hpp"
auto operator"" _ms(unsigned long long n)
{
return std::chrono::milliseconds(n);
}
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500_ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
367
Hello
..
35
user-defined literals (UDL)
#include "required_headers.hpp"
auto operator"" _ms(unsigned long long n)
{
return std::chrono::milliseconds(n);
}
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500_ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
368
#include "required_headers.hpp"
auto operator"" _ms(unsigned long long n)
{
return std::chrono::milliseconds(n);
}
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500_ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
369
The C++ standard library already comes with
a handful of useful user-defined literals.
#include "required_headers.hpp"
auto operator"" _ms(unsigned long long n)
{
return std::chrono::milliseconds(n);
}
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500_ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
370
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
371
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
372
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
373
Hello
..
36
std::chrono_literals
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
374
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500ms);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
375
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500000000ns);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
376
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500000000ns);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
377
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500000000ns);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
378
Even nanoseconds.
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500000000ns);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
379
Even nanoseconds.
Phew, this is hard to read...
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500000000ns);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
380
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500000000ns);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
381
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500'000'000ns);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
382
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500'000'000ns);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
383
Better?
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500'000'000ns);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
384
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500'000'000ns);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
385
Hello
..
37
digits separator
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500'000'000ns);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
386
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500'000'000ns);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
387
Now for something completely different...
#include "required_headers.hpp"
using namespace std::chrono_literals;
namespace my {
void putchar(char ch)
{
std::this_thread::sleep_for(500'000'000ns);
std::cout << ch << std::flush;
}
}
std::size_t print(std::vector seq)
{
std::for_each(std::crbegin(seq), std::crend(seq), my::putchar);
return std::size(seq);
}
int main()
{
std::vector seq{'o', 'l', 'l', 'e', 'H'};
print(seq);
}
388
#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
int main()
{
std::cout << "Hello\n";
}
428
#include
int main()
{
std::cout << "Hello\n";
}
429
It is possible to print out "Hello" just like this.
#include
int main()
{
std::cout << "Hello\n";
}
430
#include
int main()
{
std::cout << "Hello\n";
}
431
Hello
..
42
just "Hello"
432
!
433
1. iterators
2. std::cbegin() / std::cend()
3. type deduction and auto
4. {} initialization (aka brace initialization)
5. std::for_each
6. user-defined container and pass by const ref
7. std::array
8. std::vector
9. std::sort and pass by value (copy)
10. erase-remove idiom
11. algorithms and high level optimization
12. std::function
13. function objects (aka functors)
14. lambda expression and generalized lambda capture
15. wrap functions with lambda expressions
16. function template and dependent names
17. type traits and static assert
18. enable_if
19. concepts and requires (C++20?)
20. concepts as template parameters (C++20?)
21. concepts in function declaration (C++23?)
22. pass by lvalue reference
23. pass by rvalue reference and std::move
24. return value optimization and copy elision
25. the std::vector move constructor
26. std::tuple, structural binding and if statement with initializer
27. reverse iterators
28. namespace and my::putchar
29. chrono and sleep_for
30. std::invoke
31. async, future and promise
32. std::launch::deferred
33. std::launch::async
34. silly operator overload (don't do this)
35. user-defined literals
36. std::chrono_literals
37. digits separator
38. std::string
39. std::string_view and range-for
40. string literals
41. constexpr
42. just "Hello"
434
435
Still here? OK, one more then...
#include "required_headers.hpp"
namespace my {
void putchar(char ch, long delay)
{
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
std::cout << ch << std::flush;
}
}
void print(std::vector seq)
{
std::vector> futures(std::size(seq));
for (char ch : seq)
futures.emplace_back(std::async(my::putchar, ch, ch));
}
int main()
{
std::vector seq{'e', 'l', 'H', 'o', 'l'};
print(seq);
}
436
Hello
..
sleep sort