Injustice - Developers Among Us (SciFiDevCon 2024)
C++ in the 21st Century
1. C++ in the 21st Century
arvid@bittorrent.com
September 2013
For Internal Presentations Only, Not For External Distribution.
2. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
C++11
• for loops
• automatic type deduction
• lambda functions
• override specifier
• smart pointers
• error_code
• chrono
3. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
• for loops
• automatic type deduction
• lambda functions
• override specifier
• smart pointers
• error_code
• chrono library features
core language features
C++11
5. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
for (std::vector<int>::iterator i = v.begin()!
, end(v.end()); i != end; ++i) {!
print(*i);!
}!
int v[] = {1, 3, 3, 7};!
for (int i = 0; i < sizeof(v)/sizeof(v[0]); ++i) {!
print(v[i]);!
}!
C++98
6. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
for (int a : v) {!
print(a);!
}!
C++11 For
7. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
for (auto i = begin(v), _end(end(v));!
i != _end; ++i) {!
int a = *i;!
print(a);!
}!
Conceptually expands to something like this:
C++11 For
8. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
Conceptually expands to something like this:
argument dependent lookup,
to support user defined types
for (auto i = begin(v), _end(end(v));!
i != _end; ++i) {!
int a = *i;!
print(a);!
}!
C++11 For
9. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
template<class A, int N>!
A* begin(A a[N]) { return &a[0]; }!
!
template<class A, int N>!
A* end(A a[N]) { return &a[N]; }!
!
This is why it also works for C-arrays
C++11 For
10. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
for loops
automatic type deduction
lambda functions
override specifier
smart pointers
error_code
chrono
C++11 For
12. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
New use of keyword auto - automatically deduces the type
of a variable declaration.
New keyword decltype() - deduces the type of an
expression. This can be used in type expressions other than
variable declarations, such as template arguments.
C++11 Auto
13. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
C++11 Declytype
std::vector<decltype(f())> vals;!
std::generate_n(std::back_inserter(vals), 10, &f);!
14. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
std::vector<decltype(f())> vals;!
std::generate_n(std::back_inserter(vals), 10, &f);!
f() is not evaluated, similar to sizeof().
decltype expression is a type
C++11 Declytype
15. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
std::map<std::string, int> m;!
!
std::map<std::string, int>::iterator i =!
m.find(“foobar”);!
if (i == m.end()) return;!
C++98 Auto
16. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
std::map<std::string, int> m;!
!
auto i = m.find(“foobar”);!
if (i == m.end()) return;!
C++11 Auto
17. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
std::map<std::string, int> m;!
!
auto i = m.find(“foobar”);!
if (i == m.end()) return;!
Type deduced from return
type of function call
C++11 Auto
18. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
std::map<std::string, int> m;!
!
auto i = m.find(“foobar”);!
if (i == m.end()) return;!
conceptually: decltype(m.find(“foobar”)) i = ...
C++11 Auto
19. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
• for loops
• automatic type deduction
• lambda functions
• override specifier
• smart pointers
• error_code
• chrono
C++11 Auto
21. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
C++98 Function objects
struct is_divisible_by {!
is_divisible_by(int denom): d(denom) {}!
bool operator()(int n) const!
{ return n % d == 0; }!
int d;!
}!
!
std::vector<int>::iterator i =!
std::find_if(v.begin()!
, v.end(), is_divisible_by(x));!
22. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
bool is_divisible_by()(int n, int d)!
{ return n % d == 0; }!
!
std::vector<int>::iterator i =!
std::find_if(v.begin()!
, v.end(), std::bind(&is_divisible_by, _1, x));!
C++03 Function objects
23. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
bool is_divisible_by()(int n, int d)!
{ return n % d == 0; }!
!
std::vector<int>::iterator i =!
std::find_if(v.begin()!
, v.end(), std::bind(&is_divisible_by, _1, x));!
Partially applied function
C++03 Function objects
24. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
C++11 Function objects
auto i = std::find_if(v.begin()!
, v.end(), [=](int n) { return n % x == 0; });!
25. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
C++11 Function objects
• New syntax for lambda functions.
• Expressions that implicitly create function objects
that captures referenced values from the scope.
• Values can be captured by value, by reference or both
26. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
std::vector<int> v = {1,2,3,4,5,6,7};!
int x = 2;!
auto i = std::find_if(v.begin()!
, v.end(), [=](int n) { return n % x == 0; });!
copy x into lambda scope
capture expression (copy)
C++11 Function objects
27. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
[=](int n) { return n % x == 0; });!
copy captured variables from context
!
!
[&](int n) { return n % x == 0; });!
capture context variables by reference (lvalues)
!
!
[&x](int n) { return n % x == y; });!
explicitly capture x by reference, anything else is
captured by copy
C++11 Function objects
28. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
auto i = std::transform(v.begin(), v.end()!
, [=](double n) -> double!
{ if (n < 0.1) return 0; else return n; });!
!
!
If the compiler fails to deduce return type for the lambda, it can
be specified with the -> syntax.
C++11 Function objects
29. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
• for loops
• automatic type deduction
• lambda functions
• override specifier
• smart pointers
• error_code
• chrono
C++11
31. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
C++11 Override specifier
struct shape { virtual void draw(); };!
!
struct rectangle : shape!
{ virtual void draw() const; };!
32. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
struct shape { virtual void draw(); };!
!
struct rectangle : shape!
{ virtual void draw() const; };!
Does not override shape’s draw!
C++11 Override specifier
33. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
struct shape { virtual void draw(); };!
!
struct rectangle : shape!
{ virtual void draw() const override; };!
tell the compiler that we want this to
override a function from the base class
Error: Has a different signature
from ‘shape::draw’!
C++11 Final specifier
34. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
struct shape : entity!
{ virtual void move(); };!
!
struct rectangle : shape!
{ virtual void move(); };!
C++11 Final specifier
35. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
struct shape : entity!
{ virtual void move() final; };!
!
struct rectangle : shape!
{ virtual void move(); };!
not allowed to be overridden!
Error: move cannot be overridden as
it's final in ‘shape’!
C++11 Final specifier
36. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
• for loops
• automatic type deduction
• lambda functions
• override specifier
• smart pointers
• error_code
• chrono
C++11
38. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
template <class T> unique_ptr<T>;!
delete object when pointer goes out of scope. pointer
is not copyable (but movable).
replaces the somewhat broken std::auto_ptr<T>.
Useful for returning heap allocated objects and
constructing temporary heap objects.
C++11 Smart pointers
39. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
std::unique_ptr<A> a = new A;!
!
a->foo();!
a->bar();!
!
// a is deleted at the end of the scope
// typically one would just create A
// on the stack in this case
C++11 Smart pointers
40. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
std::unique_ptr<shape> get_new_shape() {!
switch (std::rand() % 2) {!
case 0: return new rectangle();!
case 1: return new circle();!
}!
}!
!
users of this function do not need to think about object
ownership or lifetime.
C++11 Smart pointers
41. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
template <class T> shared_ptr<T>;!
delete object when last pointer goes out of scope.
pointer is copyable and reference counting.
template <class T> weak_ptr<T>;!
non reference counting pointer to object held by
shared_ptr.
template <class T, ...A>!
shared_ptr<T> make_shared(A... args);!
constructs an instance of T held by a shared_ptr.
C++11 Smart pointers
42. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
shared_ptr<socket> c = make_shared<socket>();!
c->connect(/* ... */);!
c->async_read([=] (size_t, error_code const&)!
{ c->async_write(...); });!
// as long as the operation is outstanding,
// the connection object is kept alive
C++11 Smart pointers
43. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
• for loops
• automatic type deduction
• lambda functions
• override specifier
• smart pointers
• error_code
• chrono
C++11
45. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
Using an integer for errors:
+ easy to programmatically handle errors
+ error message can be localized
- which domain does the error belong to (posix,
http, openssl, windows, ...)
- not easily interpreted by human (especially
with domain unknown)
C++11 Error_code
46. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
Using a string for errors:
+ easily interpreted by humans
- hard to programmatically handle errors
- which domain does the error belong to?
(not clear unless the string is verbose)
- essentially impossible to localize
C++11 Error_code
47. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
error_code represents an error and solves all of those
problems.
error_code has an integral error_value, indicating the error
as well as a category, indicating the domain of the
error_value.
category is an abstract base class implementing error_value -
> human error message.
category is critical for compossibility.
C++11 Error_code
48. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
tcp::socket s;!
error_code ec;!
s.connect(/* ... */, ec);!
if (ec) {!
printf(“failed to connect: [%s:%d] %sn”!
, ec.category().name()!
, ec.value()!
, ec.message().c_str());!
exit(1);!
}!
!
!
C++11 Error_code
49. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
using an error_code for errors:
!
+ easily interpreted by humans!
+ easy to programmatically handle errors!
+ clear which domain the error belongs to!
+ possible to localize!
C++11 Error_code
50. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
• for loops
• automatic type deduction
• lambda functions
• override specifier
• smart pointers
• error_code
• chrono
C++11
52. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
Nanosecond resolution and millennia range of timestamps?
(both do not fit in 64 bits)
Separate functions for second, millisecond, microsecond
resolution clocks?
Floating point timestamps?
Type safety of timestamps?
(pass in microseconds to a sleep that takes milliseconds, then wait...)
C++11 Chrono
53. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
in C++98 and POSIX, we have the following timers:
std::clock() / CLOCKS_PER_SEC
time()
clock_gettime() / clock_getres()
gettimeofday()
C++98 Chrono
54. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
in C++98 and POSIX, we have the following timers:
std::clock() / CLOCKS_PER_SEC
time()
clock_gettime() / clock_getres()
gettimeofday()
nanosecond resolution,
but is not monotonic (daylight
savings, ntpd adjustments)
high resolution and
monotonic. not supported on
windows and some POSIX
very low resolution
second resolution, not monotonic
C++98 Chrono
55. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
Chrono introduces an abstract concept of a clock,
with its own epoch and its own resolution.
time_point - a point in time, relative to the epoch
time_duration - a delta between two time points,
a certain number of ticks.
C++11 Chrono
56. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
To query the current time:
clock::time_point timestamp = clock::now();
C++11 provides 3 standard clocks:
std::chrono::system_clock - real-time clock
std::chrono::steady_clock - guaranteed to be monotonic
std::chrono::high_resolution_clock - system’s highest resolution
C++98 Chrono
57. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
the time_point and time_duration types have their resolution
encoded in their types.
duration<int,ratio<1,1000000000>> nanoseconds;!
duration<int,ratio<1,1000000>> microseconds;!
duration<int,ratio<1,1000>> milliseconds;!
duration<int,ratio<1,1>> seconds;!
duration<int,ratio<60,1>> minutes;!
duration<int,ratio<3600,1>> hours;!
C++11 Chrono
58. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
conversion of resolution is automatic, i.e. you have type safety
void sleep(milliseconds s);!
sleep(seconds(10)); // OK!!
C++11 Chrono
59. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
duration<int,ratio<1,3>> d1(1); // 1 tick of 1/3 second!
duration<int,ratio<1,5>> d2(1); // 1 tick of 1/5 second!
!
auto d = d1 + d2;!
// yields 8 ticks of 1/15th seconds!
// duration<int,ratio<1,15>> d(8);!
!
d2 < d1 // yields true!
C++11 Chrono
60. For Internal Presentation Purposes Only, Not For External Distribution .BitTorrent, Inc. | C++ in the 21st Century
range-for: for (int a : v) { printf(“%dn”, a); }!
keywords: auto decltype override final!
lambda: [=](int x) { return x % n == 0; }!
smart ptrs: shared_ptr<> make_shared<> unique_ptr<>!
types: error_code, time_point, time_duration!
Thank You
C++11
Hinweis der Redaktion
Feel free to interrupt if I’m wrong about something, if I have a bug or if you have a question. These are the features I will cover. I haven’t actually had time to proof read this very carefully, nor test all code snippets.
4 language features and 3 new library additions.
One small but important new feature is the for loop. Vastly simplifies the common case to make it less error prone.
the C and C++98 for loop. using iterators for STL containers and indices for arrays. imagine if the loop bodies were a bit bigger, your assumption about the for loop hinge on the body not modifying the iterator.
C++11 adds a range-for loop. No iterator/counter. right of the colon is any container type satisfying the interface for a container, begin() and end() functions.
The loop can be thought of expanding to something like this. The type of v must have two free functions begin() and end().
explain argument dependent lookup. Introduced primarily for operator overloading, but is extremely useful for constructing compossible interfaces. The begin() and end() functions are looked for in the same namespace as the type of v is defined in.
That’s how it works for C arrays. The standard library defines functions that can be thought of looking something like this
automatic type deduction is another major feature in C++11, where you can leverage the compilers ability to deduce types
auto can be used to specify “whatever type works here”. decltype() is a type-expression that can be used for template arguments for instance.
decltype is used to produce the type of the return value of f().
C++ introduces anonymous function objects, referred to as lambda functions. To understand what they are, let’s start at the beginning in 1998.
find the first element in v that is divisible by a number (x). create a function object (note the function call operator). This object holds the state of the parameter x.
in C++03 the bind function is introduced. It significantly simplifies binding values to functions. There is no longer a need to make the predicate function an object, it can be a plain function.
bind introduces partially applied functions, just like in functional languages. It returns a new function object where some of the arguments of the original function have been bound to some values. In this case x is bound to the second argument of is_divisible_by.
The lambda function automatically captures variables from the enclosing scope into a function object that is created implicitly.
To tell the compiler what return type to use, specify it with the -&gt; syntax. If the compiler fail to deduce the return type.
Every time you start a new C++ project, and you go about setting up your shape hierarchy, you run the risk of falling into this trap.
your rectangles are never drawn!
the override keyword diagnose this at compile time
let’s say shape derives from entity, and you don’t want shapes to be able to implement their own move function.
replaces std::auto_ptr&lt;&gt;. takes great advantage of move semantics. unique because there’s always exactly one pointer pointing to the held object.
can be used as a scoped_ptr&lt;&gt;, where you want to allocate an object on the heap with scope-lifetime.
can be used to return heap allocated objects with no ownership issue.
shared ownership, where multiple pointers point to the same object, each of them keeping it alive. Only when the last pointer/reference goes away, is the object deleted.
contrived example. the asynchronous operation keeps the socket object alive.