Page 1
Introduction to modern C++Olve Maudal
45 minute presentation for Thales Norway, Competence Day Oct 24, 2014
C++ has evolved a lot since it was first introduced as "C with classes" with primitive support for object-oriented programming. In particular during the last 10-15 years the common use of the language has changed "dramatically" and the language itself has evolved accordingly. Modern C++ (C++11/14) is still very suitable for object-oriented programming, but now the language also provides good support for generic programming and functional programming. All of this while C++ is still a low-level language that can be used to create programs that compete with programs written in assembler both in terms of speed and size.
We start with a brief history of C++ before focusing on new features in C++11/14 and a demonstration of some typical modern programming techniques.
Page 2
• Brief History of C and C++•New features in C++11/14•Generic Programming•The future of C++
Page 3
• Evolution of Ski Jumping• Brief History of C and C++•New features in C++11/14•Generic Programming•The future of C++
Page 4
Evolution of Ski Jumping
Page 5
http://www.aftenposten.no/fakta/innsikt/Da-skiene-ble-vinger-7459947.html
Page 7
Kongsberg knekk, Birger Ruud (1947)
Page 8
Matti Pietikäinen (1954)
Page 9
Helmut Recknagel (~1960)
Page 10
Finnestilen, Bjørn Wirkola (1964)
Page 11
Finnestilen, Lars Grini (1967)
Page 12
Sideflyt, Per Bergerud (1981)
Page 13
Sideflyt, Per Bergerud (1983)
Page 14
V-stilen, Jan Bokløv (1989)
Page 15
Kamikaze, Noriaki Kasai (2004)
Page 16
Dykkstil/W-stil, Andreas Wank (2012)
Page 17
Brief History of C and C++
Page 18
40'sMachine code, symbol tables and Assembler
Page 19
50'sFortran, Lisp, Cobol, Algol
Page 20
50'sFortran, Lisp, Cobol, Algol
Page 21
60'smany, many new languages appeared in this period. In particular...
Page 22
60'sCPL and Simula
Page 23
60'sCPL and Simula
Both CPL and Simula were examples of very elegant languages...
Page 24
... but there was also a need for brutally efficient languages
Page 25
70'sBCPL, B, C
... but there was also a need for brutally efficient languages
Page 26
80'sC with classes, C++/CFront, ARM
After frustrating experience with BCPL, Bjarne Stroustrup combined the efficiency of C with some of the elegance from Simula...
Page 27
90'sX3J16, C++arm, WG21, C++98, STL
C++ was improved and became standardized
Page 28
Ouch... Template Metaprogramming
Page 29
C++03, TR1, Boost and other external libraries
While the language itself saw some minor improvements after C++98, Boost and other external libraries acted like laboratories for experimenting with potential new C++ features. Resulting in...
Page 30
C++11/C++14
With the latest version C++ feels like a new language
Page 31
The next major version is expected in 2017
Page 32
The future of C++?
Page 33
• PhD, Simula, BCPL (Cambridge)• C with Classes (Cpre, 1979)• First external paper (1981)• C++ named (1983)• CFront 1.0 (1985)• TC++PL, Ed1 (1985)• ANSI X3J16 meeting (1989)• The Annotated C++ Reference Manual (1990)• First WG21 meeting (1991)• The Design and Evolution of C++ (1994)• ISO/IEC 14882:1998 (C++98) • ISO/IEC 14882:2003 (C++03)• ISO/IEC TR 19768:2007 (C++TR1)• ISO/IEC 14882:2011 (C++11)• soon ISO/IEC 14882:2014 (C++14)
History of C++
Page 34
Modern C++ by Example
unless specified otherwise, all these code snippets should compile cleanly with a modern C++ compiler
Page 35
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (std::vector<int>::const_iterator it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 36
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (std::vector<int>::const_iterator it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Consider this small toy program...
Page 37
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (std::vector<int>::const_iterator it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Consider this small toy program...
$ g++-4.9 -std=c++1y -Wall -Wextra -pedantic -Werror foo.cpp && ./a.out20243742234537$
Page 38
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (std::vector<int>::const_iterator it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 39
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (std::vector<int>::const_iterator it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
This shows a "traditional" way of looping through a collection
of objects.
Page 40
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (std::vector<int>::const_iterator it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 41
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (std::vector<int>::const_iterator it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
But why do we have to write all this stuff? In this case, wouldn't it be nice if
the compiler could just figure out which type we need to store the
return value from log.cbegin()?
Page 42
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (std::vector<int>::const_iterator it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 43
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (std::vector<int>::const_iterator it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 44
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (decltype(log.cbegin()) it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 45
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (decltype(log.cbegin()) it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
decltype gives us type deduction in C++. Or even
better...
Page 46
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (auto it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 47
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (auto it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
We can just use the new meaning of the keyword auto
Page 48
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (auto it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 49
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (auto it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 50
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (auto it = log.cbegin(); it != log.cend(); ++it)
transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 51
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (auto it = log.cbegin(); it != log.cend(); ++it)
transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 52
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (auto it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 53
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (auto it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 54
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (auto it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 55
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (auto it = log.cbegin(); it != log.cend(); ++it) transmit_item(*it);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Looping through an array like this is something C++ programmers often do. So the language now provides a new way of looping through ranges
of objects.
Page 56
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (auto i : log) transmit_item(i);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 57
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (auto i : log) transmit_item(i);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Introducing: range based for-loop.
Page 58
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (auto i : log) transmit_item(i);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 59
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (auto i : log) transmit_item(i);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);} Sometimes we might want to
save some object copies by writing...
Page 60
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (auto i : log) transmit_item(i);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);} Sometimes we might want to
save some object copies by writing...
Page 61
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (const auto & i : log) transmit_item(i);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 62
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (const auto & i : log) transmit_item(i);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 63
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (const auto & i : log) transmit_item(i);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
But even for simple loops like this you will often see that
STL algorithms are used instead.
Page 64
#include <iostream>#include <vector>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (const auto & i : log) transmit_item(i);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 65
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (const auto & i : log) transmit_item(i);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 66
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ for (const auto & i : log) transmit_item(i);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 67
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ std::for_each(log.begin(), log.end(), transmit_item);
}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 68
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ std::for_each(log.begin(), log.end(), transmit_item);
}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 69
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ std::for_each(log.begin(), log.end(), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 70
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ std::for_each(log.begin(), log.end(), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 71
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ std::for_each(log.begin(), log.end(), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
You will often see this written as...
Page 72
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ std::for_each(log.begin(), log.end(), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
You will often see this written as...
Page 73
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 74
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Because it now works on both containers and arrays.
Page 75
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 76
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Suppose we would like to sort the array before transmitting the
items...
Page 77
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Suppose we would like to sort the array before transmitting the
items...
First we make a local copy of the log through a
pass-by-value
Page 78
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Suppose we would like to sort the array before transmitting the
items...
First we make a local copy of the log through a
pass-by-value
Page 79
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> log){ std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 80
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> log){ std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 81
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 82
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 83
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
But wait! What if the log has million of entries? Perhaps we should do pass-by-
reference instead?
Page 84
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
But wait! What if the log has million of entries? Perhaps we should do pass-by-
reference instead?
Page 85
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> & log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 86
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> & log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
Page 87
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> & log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
This works. But, in this case, it would be even
better if we had an option to pass the ownership of the log to transmit_log by reference so it can do
whatever it wants.
Page 88
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> & log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
This works. But, in this case, it would be even
better if we had an option to pass the ownership of the log to transmit_log by reference so it can do
whatever it wants.
Page 89
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> & log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(log);}
This works. But, in this case, it would be even
better if we had an option to pass the ownership of the log to transmit_log by reference so it can do
whatever it wants.
Page 90
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Page 91
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Page 92
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Page 93
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
This is an rvalue reference.
Page 94
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
This is an rvalue reference.
Page 95
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
This is an rvalue reference.
And here we basically say: Just take this data object, it is yours, do whatever you want with it. I promise
to never refer to it again after this.
Page 96
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
This is an rvalue reference.
And here we basically say: Just take this data object, it is yours, do whatever you want with it. I promise
to never refer to it again after this.
rvalue references and the corresponding move semantics are very important contributions to modern C++. It reduces the need to create copies of
objects while still being able to use value semantics as a programming style (ie, avoiding the need to use pointers for everything).
Page 97
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Page 98
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Typical for most algorithms in the C++ library is that you can adapt them to your own needs. Let's try to
change the sorting order by writing our own comparator function.
Page 99
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Typical for most algorithms in the C++ library is that you can adapt them to your own needs. Let's try to
change the sorting order by writing our own comparator function.
Page 100
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...} static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Typical for most algorithms in the C++ library is that you can adapt them to your own needs. Let's try to
change the sorting order by writing our own comparator function.
Page 101
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static bool mycomp(int lhs, int rhs) { return lhs > rhs;}
static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log), mycomp); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Page 102
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static bool mycomp(int lhs, int rhs) { return lhs > rhs;}
static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log), mycomp); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Page 103
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static bool mycomp(int lhs, int rhs) { return lhs > rhs;}
static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log), mycomp); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
This is a typical way to introduce a strategy into an existing algorithm. (Here you could have used
std::greater as well, but if you want something more complex you need to write it yourself.)
Page 104
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static bool mycomp(int lhs, int rhs) { return lhs > rhs;}
static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log), mycomp); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
This is a typical way to introduce a strategy into an existing algorithm. (Here you could have used
std::greater as well, but if you want something more complex you need to write it yourself.)
It depends on the context, but in this case you might want to allow the caller to pass the strategy in into
transmit_log()
Page 105
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static bool mycomp(int lhs, int rhs) { return lhs > rhs;}
static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log), mycomp); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
This is a typical way to introduce a strategy into an existing algorithm. (Here you could have used
std::greater as well, but if you want something more complex you need to write it yourself.)
It depends on the context, but in this case you might want to allow the caller to pass the strategy in into
transmit_log()
Page 106
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static bool mycomp(int lhs, int rhs) { return lhs > rhs;}
static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log), mycomp); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
This is a typical way to introduce a strategy into an existing algorithm. (Here you could have used
std::greater as well, but if you want something more complex you need to write it yourself.)
It depends on the context, but in this case you might want to allow the caller to pass the strategy in into
transmit_log()
Page 107
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static bool mycomp(int lhs, int rhs) { return lhs > rhs;}
static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log), mycomp); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
This is a typical way to introduce a strategy into an existing algorithm. (Here you could have used
std::greater as well, but if you want something more complex you need to write it yourself.)
It depends on the context, but in this case you might want to allow the caller to pass the strategy in into
transmit_log()
Page 108
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static bool mycomp(int lhs, int rhs) { return lhs > rhs;}
static void transmit_log(std::vector<int> && log, bool comp(int, int)){ std::sort(std::begin(log), std::end(log), comp); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), mycomp);}
Page 109
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static bool mycomp(int lhs, int rhs) { return lhs > rhs;}
static void transmit_log(std::vector<int> && log, bool comp(int, int)){ std::sort(std::begin(log), std::end(log), comp); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), mycomp);}
This is an example of parameterize from above
Page 110
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static bool mycomp(int lhs, int rhs) { return lhs > rhs;}
static void transmit_log(std::vector<int> && log, bool comp(int, int)){ std::sort(std::begin(log), std::end(log), comp); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), mycomp);}
Page 111
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static bool mycomp(int lhs, int rhs) { return lhs > rhs;}
static void transmit_log(std::vector<int> && log, bool comp(int, int)){ std::sort(std::begin(log), std::end(log), comp); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), mycomp);}
I am now going to introduce function objects and lambdas. Let's
simplify the code, before introducing a algorithms for
filtering out and removing log values.
Page 112
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static bool mycomp(int lhs, int rhs) { return lhs > rhs;}
static void transmit_log(std::vector<int> && log, bool comp(int, int)){ std::sort(std::begin(log), std::end(log), comp); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), mycomp);}
I am now going to introduce function objects and lambdas. Let's
simplify the code, before introducing a algorithms for
filtering out and removing log values.
Page 113
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static bool mycomp(int lhs, int rhs) { return lhs > rhs;}
static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Page 114
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static bool mycomp(int lhs, int rhs) { return lhs > rhs;}
static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Page 115
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Page 116
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log){ std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Page 117
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log){ struct filter { filter(int limit) : lim(limit) {} bool operator()(int i) { return i <= lim; }; int lim; } myfilter(23); log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Page 118
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log){ struct filter { filter(int limit) : lim(limit) {} bool operator()(int i) { return i <= lim; }; int lim; } myfilter(23); log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Here we have created code to remove all log items that are 23 or
below.
Page 119
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log){ struct filter { filter(int limit) : lim(limit) {} bool operator()(int i) { return i <= lim; }; int lim; } myfilter(23); log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Page 120
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log){ struct filter { filter(int limit) : lim(limit) {} bool operator()(int i) { return i <= lim; }; int lim; } myfilter(23); log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Notice how we have created a "function" on the fly by overloading the call operator on an
object. This is an example of a function object, sometimes called a functor.
Page 121
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log){ struct filter { filter(int limit) : lim(limit) {} bool operator()(int i) { return i <= lim; }; int lim; } myfilter(23); log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Page 122
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log){ struct filter { filter(int limit) : lim(limit) {} bool operator()(int i) { return i <= lim; }; int lim; } myfilter(23); log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Suppose we want to parameterize from above again, by passing in the limit.
Page 123
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log){ struct filter { filter(int limit) : lim(limit) {} bool operator()(int i) { return i <= lim; }; int lim; } myfilter(23); log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Suppose we want to parameterize from above again, by passing in the limit.
Page 124
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log){ struct filter { filter(int limit) : lim(limit) {} bool operator()(int i) { return i <= lim; }; int lim; } myfilter(23); log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Suppose we want to parameterize from above again, by passing in the limit.
Page 125
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log){ struct filter { filter(int limit) : lim(limit) {} bool operator()(int i) { return i <= lim; }; int lim; } myfilter(23); log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log));}
Suppose we want to parameterize from above again, by passing in the limit.
Page 126
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, int limit){ struct filter { filter(int limit) : lim(limit) {} bool operator()(int i) { return i <= lim; }; int lim; } myfilter(limit); log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), 23);}
Page 127
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, int limit){ struct filter { filter(int limit) : lim(limit) {} bool operator()(int i) { return i <= lim; }; int lim; } myfilter(limit); log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), 23);}
Page 128
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, int limit){ struct filter { filter(int limit) : lim(limit) {} bool operator()(int i) { return i <= lim; }; int lim; } myfilter(limit); log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), 23);}
Such function objects are sometimes very useful. New in C++11 is a convenient syntax
for creating these functions.
Page 129
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, int limit){ struct filter { filter(int limit) : lim(limit) {} bool operator()(int i) { return i <= lim; }; int lim; } myfilter(limit); log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), 23);}
Such function objects are sometimes very useful. New in C++11 is a convenient syntax
for creating these functions.
Page 130
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, int limit){ struct filter { filter(int limit) : lim(limit) {} bool operator()(int i) { return i <= lim; }; int lim; } myfilter(limit); log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), 23);}
Page 131
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, int limit){ struct filter { filter(int limit) : lim(limit) {} bool operator()(int i) { return i <= lim; }; int lim; } myfilter(limit); log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), 23);}
Page 132
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, int limit){ auto myfilter = [limit](int i) { return i <= limit; }; log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), 23);}
Page 133
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, int limit){ auto myfilter = [limit](int i) { return i <= limit; }; log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), 23);}
Page 134
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, int limit){ auto myfilter = [limit](int i) { return i <= limit; }; log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), 23);}
Page 135
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, int limit){ auto myfilter = [limit](int i) { return i <= limit; }; log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), 23);}
This is a lambda expression that creates a function object on the "fly". We are
capturing the value of the variable limit and using it to initialize the function object.
Page 136
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, int limit){ auto myfilter = [limit](int i) { return i <= limit; }; log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), 23);}
Page 137
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, int limit){ auto myfilter = [limit](int i) { return i <= limit; }; log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), 23);}
You can of course also pass function objects around as any other objects.
Page 138
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, int limit){ auto myfilter = [limit](int i) { return i <= limit; }; log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), 23);}
You can of course also pass function objects around as any other objects.
Page 139
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, int limit){ std::function<bool (int)> myfilter = [limit](int i) { return i <= limit; }; log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), 23);}
Page 140
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, int limit){ std::function<bool (int)> myfilter = [limit](int i) { return i <= limit; }; log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), 23);}
Page 141
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, std::function<bool (int)> myfilter){
log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
Page 142
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, std::function<bool (int)> myfilter){
log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
Page 143
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, std::function<bool (int)> myfilter){
log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
Page 144
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, std::function<bool (int)> myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
Page 145
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, std::function<bool (int)> myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
Page 146
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, std::function<bool (int)> myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
Basically anything that can be called with an int and returning a bool is OK. We can
generalize the code with a template.
Page 147
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
static void transmit_log(std::vector<int> && log, std::function<bool (int)> myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
Basically anything that can be called with an int and returning a bool is OK. We can
generalize the code with a template.
Page 148
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
template <typename Filt>static void transmit_log(std::vector<int> && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
Page 149
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
template <typename Filt>static void transmit_log(std::vector<int> && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
Page 150
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
template <typename Filt>static void transmit_log(std::vector<int> && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
... and the same is true for the log. Anything that we can iterate over, and that contains some items that we can transmit should be
fine.
Page 151
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
template <typename Filt>static void transmit_log(std::vector<int> && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
... and the same is true for the log. Anything that we can iterate over, and that contains some items that we can transmit should be
fine.
Page 152
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
... and the same is true for the log. Anything that we can iterate over, and that contains some items that we can transmit should be
fine.
Page 153
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
And while we are at it, let's generalize the code for transmit_item as well
Page 154
#include <iostream>#include <vector>#include <algorithm>#include <functional>
static void transmit_item(int i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
And while we are at it, let's generalize the code for transmit_item as well
Page 155
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<int>);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
Page 156
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<int>);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
Page 157
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<int>);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
Page 158
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<int>);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
Page 159
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
Page 160
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
Page 161
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
transmit_log and transmit_item are now type independent code. This is a fine example of generic programming. Notice how we can change both the type of the log
items and the container and it should still work (given some restrictions)
Page 162
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
transmit_log and transmit_item are now type independent code. This is a fine example of generic programming. Notice how we can change both the type of the log
items and the container and it should still work (given some restrictions)
Page 163
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
transmit_log and transmit_item are now type independent code. This is a fine example of generic programming. Notice how we can change both the type of the log
items and the container and it should still work (given some restrictions)
Page 164
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](int i) { return i <= 23; });}
transmit_log and transmit_item are now type independent code. This is a fine example of generic programming. Notice how we can change both the type of the log
items and the container and it should still work (given some restrictions)
Page 165
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
Page 166
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
Page 167
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
Page 168
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
Page 169
#include <iostream>#include <deque>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::deque<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
Page 170
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
Page 171
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
Page 172
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
It would be nice to specify exactly what expectations we have to the types and objects that are passed into
our generic code. A "poor man" solution is to use type traits and static_assert.
Page 173
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
It would be nice to specify exactly what expectations we have to the types and objects that are passed into
our generic code. A "poor man" solution is to use type traits and static_assert.
Page 174
#include <iostream>#include <vector>#include <algorithm>#include <functional>
template <typename T>static void transmit_item(T i){ std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
It would be nice to specify exactly what expectations we have to the types and objects that are passed into
our generic code. A "poor man" solution is to use type traits and static_assert.
Page 175
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>
template <typename T>static void transmit_item(T i){ static_assert(std::is_integral<T>::value, "integral type expected"); std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
Page 176
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>
template <typename T>static void transmit_item(T i){ static_assert(std::is_integral<T>::value, "integral type expected"); std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
Page 177
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>
template <typename T>static void transmit_item(T i){ static_assert(std::is_integral<T>::value, "integral type expected"); std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
Here we will get an understandable compile error if the type of the log items are not of integral type.
However, you can, with some work, define your own traits and constraints. Eg, something like this:
Page 178
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>
template <typename T>static void transmit_item(T i){ static_assert(std::is_integral<T>::value, "integral type expected"); std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
Here we will get an understandable compile error if the type of the log items are not of integral type.
However, you can, with some work, define your own traits and constraints. Eg, something like this:
Page 179
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>
template <typename T>static void transmit_item(T i){ static_assert(std::is_integral<T>::value, "integral type expected"); std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
Here we will get an understandable compile error if the type of the log items are not of integral type.
However, you can, with some work, define your own traits and constraints. Eg, something like this:
Page 180
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>#include "mystuff"
template <typename T>static void transmit_item(T i){ static_assert(my::is_transmittable<T>::value, "transmittable type expected"); std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
Xthis is just an e ample that does not compile
Page 181
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>#include "mystuff"
template <typename T>static void transmit_item(T i){ static_assert(my::is_transmittable<T>::value, "transmittable type expected"); std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
Xthis is just an e ample that does not compile
Page 182
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>#include "mystuff"
template <typename T>static void transmit_item(T i){ static_assert(my::is_transmittable<T>::value, "transmittable type expected"); std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
Xthis is just an e ample that does not compile
There are some proposals for the next versions of C++ to include better syntax for such constraints.
Page 183
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>#include "mystuff"
template <typename T>static void transmit_item(T i){ static_assert(my::is_transmittable<T>::value, "transmittable type expected"); std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
Xthis is just an e ample that does not compile
There are some proposals for the next versions of C++ to include better syntax for such constraints.
Page 184
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>#include "mystuff"
template <typename T> require Transmittable<T>static void transmit_item(T i) {
std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
X
Page 185
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>#include "mystuff"
template <typename T> require Transmittable<T>static void transmit_item(T i) {
std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
X
Page 186
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>#include "mystuff"
template <typename T> require Transmittable<T>static void transmit_item(T i) {
std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
X
Page 187
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>#include "mystuff"
template <Transmittable T>static void transmit_item(T i) {
std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
X
Page 188
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>#include "mystuff"
template <Transmittable T>static void transmit_item(T i) {
std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
X
Page 189
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>#include "mystuff"
template <Transmittable T>static void transmit_item(T i) {
std::cout << i << std::endl; // ...}
template <typename Log, typename Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
X
Page 190
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>#include "mystuff"
template <Transmittable T>static void transmit_item(T i) {
std::cout << i << std::endl; // ...}
template <Iterable Log, UnaryFunctionPredicate Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
X
Page 191
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>#include "mystuff"
template <Transmittable T>static void transmit_item(T i) {
std::cout << i << std::endl; // ...}
template <Iterable Log, UnaryFunctionPredicate Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
X
Page 192
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>#include "mystuff"
template <Transmittable T>static void transmit_item(T i) {
std::cout << i << std::endl; // ...}
template <Iterable Log, UnaryFunctionPredicate Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
This proposal is a step towards something called Concepts. I am not going to explain that, so let's clean
up the code so I can show a final thing.
X
Page 193
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>#include "mystuff"
template <Transmittable T>static void transmit_item(T i) {
std::cout << i << std::endl; // ...}
template <Iterable Log, UnaryFunctionPredicate Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
X
Page 194
#include <iostream>#include <vector>#include <algorithm>#include <functional>#include <type_traits>#include "mystuff"
template <Transmittable T>static void transmit_item(T i) {
std::cout << i << std::endl; // ...}
template <Iterable Log, UnaryFunctionPredicate Filt>static void transmit_log(Log && log, Filt myfilter){ log.erase(std::remove_if(std::begin(log), std::end(log), myfilter), std::end(log)); std::sort(std::begin(log), std::end(log)); std::for_each(std::begin(log), std::end(log), transmit_item<typename Log::value_type>);}
int main(){ using log_item_type = long; std::vector<log_item_type> log{20,24,37,42,23,45,37}; transmit_log(std::move(log), [](log_item_type i) { return i <= 23; });}
X
Page 195
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i) { std::cout << i << std::endl; // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; size_t items = transmit_log(log); std::cout << "# " << items << std::endl;}
Page 196
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i) { std::cout << i << std::endl; // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; size_t items = transmit_log(log); std::cout << "# " << items << std::endl;}
Page 197
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i) { std::cout << i << std::endl; // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; size_t items = transmit_log(log); std::cout << "# " << items << std::endl;}
Transmitting the data probably takes some time, and we might want to do something else while waiting for
the log to be transmitted. Let's simulate that, and show an example of how concurrency is supported in
modern C++.
Page 198
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i) { std::cout << i << std::endl; // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; size_t items = transmit_log(log); std::cout << "# " << items << std::endl;}
Page 199
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i) { std::cout << i << std::endl; // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; size_t items = transmit_log(log); std::cout << "# " << items << std::endl;}
Page 200
#include <iostream>#include <vector>#include <algorithm>
static void transmit_item(int i) { std::cout << i << std::endl; // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; size_t items = transmit_log(log); std::cout << "# " << items << std::endl;}
Page 201
#include <iostream>#include <vector>#include <algorithm>#include <chrono>#include <thread>
static void transmit_item(int i) { std::cout << i << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(200)); // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; size_t items = transmit_log(log); std::cout << "# " << items << std::endl;}
Page 202
#include <iostream>#include <vector>#include <algorithm>#include <chrono>#include <thread>
static void transmit_item(int i) { std::cout << i << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(200)); // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; size_t items = transmit_log(log); std::cout << "# " << items << std::endl;}
Page 203
#include <iostream>#include <vector>#include <algorithm>#include <chrono>#include <thread>
static void transmit_item(int i) { std::cout << i << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(200)); // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; size_t items = transmit_log(log); std::cout << "# " << items << std::endl;}
Page 204
#include <iostream>#include <vector>#include <algorithm>#include <chrono>#include <thread>
static void transmit_item(int i) { std::cout << i << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(200)); // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; size_t items = transmit_log(log); std::cout << "# " << items << std::endl;}
Page 205
#include <iostream>#include <vector>#include <algorithm>#include <chrono>#include <thread>#include <future>
static void transmit_item(int i) { std::cout << i << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(200)); // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; auto res = std::async(std::launch::async, transmit_log, log); size_t items = res.get(); std::cout << "# " << items << std::endl;}
Page 206
#include <iostream>#include <vector>#include <algorithm>#include <chrono>#include <thread>#include <future>
static void transmit_item(int i) { std::cout << i << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(200)); // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; auto res = std::async(std::launch::async, transmit_log, log); size_t items = res.get(); std::cout << "# " << items << std::endl;}
$ g++-4.9 -std=c++1y -Wall -Wextra -pedantic -Werror -pthread foo.cpp
Page 207
#include <iostream>#include <vector>#include <algorithm>#include <chrono>#include <thread>#include <future>
static void transmit_item(int i) { std::cout << i << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(200)); // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; auto res = std::async(std::launch::async, transmit_log, log); size_t items = res.get(); std::cout << "# " << items << std::endl;}
Page 208
#include <iostream>#include <vector>#include <algorithm>#include <chrono>#include <thread>#include <future>
static void transmit_item(int i) { std::cout << i << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(200)); // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; auto res = std::async(std::launch::async, transmit_log, log); size_t items = res.get(); std::cout << "# " << items << std::endl;}
... and now we can do some stuff between calling transmit_log until we need the result from calling that
function.
Page 209
#include <iostream>#include <vector>#include <algorithm>#include <chrono>#include <thread>#include <future>
static void transmit_item(int i) { std::cout << i << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(200)); // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; auto res = std::async(std::launch::async, transmit_log, log); size_t items = res.get(); std::cout << "# " << items << std::endl;}
... and now we can do some stuff between calling transmit_log until we need the result from calling that
function.
Page 210
#include <iostream>#include <vector>#include <algorithm>#include <chrono>#include <thread>#include <future>
static void transmit_item(int i) { std::cout << i << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(200)); // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; auto res = std::async(std::launch::async, transmit_log, log); for (int i=0; i<5; i++) { std::this_thread::sleep_for(std::chrono::milliseconds(77)); std::cout << "do something else..." << std::endl; } size_t items = res.get(); std::cout << "# " << items << std::endl;}
Page 211
#include <iostream>#include <vector>#include <algorithm>#include <chrono>#include <thread>#include <future>
static void transmit_item(int i) { std::cout << i << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(200)); // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; auto res = std::async(std::launch::async, transmit_log, log); for (int i=0; i<5; i++) { std::this_thread::sleep_for(std::chrono::milliseconds(123)); std::cout << "do something else..." << std::endl; } size_t items = res.get(); std::cout << "# " << items << std::endl;}
Page 212
#include <iostream>#include <vector>#include <algorithm>#include <chrono>#include <thread>#include <future>
static void transmit_item(int i) { std::cout << i << std::endl; std::this_thread::sleep_for(std::chrono::milliseconds(200)); // ...}
static size_t transmit_log(const std::vector<int> & log){ std::for_each(std::begin(log), std::end(log), transmit_item); return log.size();}
int main(){ std::vector<int> log{20,24,37,42,23,45,37}; auto res = std::async(std::launch::async, transmit_log, log); for (int i=0; i<5; i++) { std::this_thread::sleep_for(std::chrono::milliseconds(123)); std::cout << "do something else..." << std::endl; } size_t items = res.get(); std::cout << "# " << items << std::endl;}
20do something else...24do something else...do something else...37do something else...42do something else...234537# 7
Page 213
Modern C++- move semantics (rvalue references, value semantics)- type deduction (decltype, auto)- better support for OOP (attributes, member initialization, delegation) - compile time computation (templates, static_assert, constexpr)- template metaprogramming (traits, constraints, concepts)- robust resource management (RAII, unique, shared)- high-order parallelism (atomic, mutex, async, promises and futures)- functional programming (algorithms, lamdas, closures, lazy evaluation)- misc (chrono, user-defined literals, regex, uniform initialization)
Page 215
http://en.wikipedia.org/wiki/C++11http://en.wikipedia.org/wiki/C++14
http://www.open-std.org/jtc1/sc22/wg21/http://en.cppreference.com/w/
http://isocpp.org
Page 216
C++ has been an inspiration for many other programming languages. For example Java, C# and D, just to mention a few
Eddie "The Eagle" Edwards (1988)