C++ in the 21st Century

621 views
460 views

Published on

BitTorrent Chief Architect Arvid Norberg Talks C++ in the 21st Century

Learn more: http://blog.bittorrent.com/tag/tech-talks/

Published in: Technology
0 Comments
5 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
621
On SlideShare
0
From Embeds
0
Number of Embeds
16
Actions
Shares
0
Downloads
24
Comments
0
Likes
5
Embeds 0
No embeds

No notes for slide
  • 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 -> 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<>. 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<>, 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.
  • C++ in the 21st Century

    1. 1. C++ in the 21st Century arvid@bittorrent.com September 2013 For Internal Presentations Only, Not For External Distribution.
    2. 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. 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
    4. 4. For Loops
    5. 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. 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. 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. 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. 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. 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
    11. 11. Automatic Type Deduction
    12. 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. 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. 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. 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. 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. 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. 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. 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
    20. 20. Function Objects
    21. 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. 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. 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. 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. 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. 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. 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. 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. 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
    30. 30. Override Specifier
    31. 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. 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. 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. 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. 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. 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
    37. 37. Smart Pointers
    38. 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. 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. 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. 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. 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. 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
    44. 44. Error_code
    45. 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. 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. 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. 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. 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. 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
    51. 51. ChronoC++ timer library
    52. 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. 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. 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. 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. 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. 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. 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. 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. 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

    ×