C++11/14 Overview - Meox Blog – a programming language resource

Transcript

C++11/14 Overview - Meox Blog – a programming language resource
www.italiancpp.org C++11/14 Overview
Gian Lorenzo Meocci
7 Febbraio Pordenone – C++ Community Meetup
Era il 1998 …
•  Marco Pantani vinceva il Giro d’Italia e il Tour de France •  Gli Aerosmith cantavano “I Don't Want to Miss a Thing” •  Page e Brin, dell'Università di Stanford, fondavano •  Veniva approvato il C++98 … Italian C++ Community
i=2 Introduction
Surprisingly, C++11 feels like a new language: The pieces just fit together be>er than they used to and I find a higher-­‐level style of programming more natural than before and as efficient as ever. Bjarne Stroustrup Goal of C++11/14 • 
• 
• 
• 
Easy to teach Backward compaKbility Performance ProducKvity Italian C++ Community
i=3 Introduction: some numbers
•  ~41 changes (and new features) to the core language •  ~27 changes to STL •  new components for STL (like regex) Big impact features: • 
• 
• 
• 
• 
auto / range for movability (rvalue ref) lambdas unique_ptr & shared_ptr Uniform IniKalizer list * Try to write it using std algorithm! Italian C++ Community
i=4 Which was the feature of new C++ that improved the
most your productivity? (Meetup Bologna)
Italian C++ Community
i=5 ZIP function (our mascot)
Let me introduce the zip func=on. This funcKon takes two list and pairs elements from the first list with the elements from the second list. Our goal is to implement it in C++14! zip :: [a] -­‐> [b] -­‐> [(a, b)] zip _ [] = [] zip [] _ = [] zip (x:xs) (y:ys) = (x, y) : zip xs ys Haskell ImplementaKon 1 2 3 4 5 6 A B C ZIP 1, A 2, B 3, C Thanks to lisperaK.com Italian C++ Community
i=6 Type Inference: auto
La moda passa, lo sHle resta (Coco Chanel) auto is a placeholder for a type. Let the compiler deduce the correct one for you! In general, we can write: auto x = expression; and the type of x will be the type of the value computed from "expression". auto x = 27; auto f = 5.4f; auto s = "hello world!"; const auto x = 42; auto& y = x; auto t = &x; auto z = y; // x is an int // f is a float // s is a const char* // x is an const int // y is a ref to a const int // t is an const int* // z is an int! *see template deduc=on rule The auto feature has the disKncKon to be the earliest to be suggested and implemented in 1984! Italian C++ Community
i=7 auto & range for
Ok but the things became more interesKng when apply to something more complex int r = 0; for (vector<int>::const_iterator it = v.begin(); it != v.end(); ++it) { if (*it % 2 == 0) r++; } Quite tedious!. The only interesKng part is the check inside int r{}; // uniform iniKalizaKon here for (const auto &e : v) { if (e % 2 == 0) r++; } Italian C++ Community
i=8 auto & range for
Using range for int r{}; // uniform iniKalizaKon here for (const auto &e : v) { if (e % 2 == 0) r++; } Prefer standard algorithm to raw loop! But we can use even an STL algorithm const int r = count_if (v.begin(), v.end(), [](const int& e) { return e % 2 == 0; }); const int r = count_if ( v , [](const auto& e) { return e % 2 == 0; }); Italian C++ Community
i=9 Uniform Initialization
In C++ we’ve different way to iniKalize basic and user defined type. C++11 introduce a new way to make iniKalizaKon of various type more uniform. // GOOD news: struct Point {int x, y;} Point p {1, 5}; Point p{}; // fix most vexing parser double d{3.5}; vector<int> v{1, 2, 3, 4, 5}; int n {5.6}; // error: narrowing! int x{42}; //fine: no narrowing // but the following sKll to be valid! int x (0); int y = 0; // these are synonymous (**) int z{}; int z {0}; int z = {0}; //but pay auenKon with auto! auto r {6}; //std::inizializer_list<int> (*) auto r = int{6}; // fine: now r is 6 * Will be fixed in C++17, ** not valid for user-­‐defined types with explicit constructors See: Back to the Basics! EssenKals of Modern C++ Style -­‐ Herb Suuer -­‐ CppCon 2014 Italian C++ Community
i=10 Uniform & In Class Initialization
We can use uniform iniKalizaKon to iniKalize non-­‐staKc data member “inline” and inside ctr. struct Widget { int x{ 0 }; // fine, x's default value is 0 int y = 0; // also fine int z(0); // error! Widget* child{nullptr}; }; Italian C++ Community
i=11 decltype: writing generic code
template <typename A, typename B> (???) mult (A a, B b) { return a * b; } Quite impossible to express it in C++98 template <typename A, typename B> auto mult (A a, B b) -­‐> decltype(a * b) { return a * b; } auto + decltype + traling return type Italian C++ Community
i=12 decltype: writing generic code
template <typename A, typename B> auto mult (A a, B b) -­‐> decltype(a * b) { return a * b; } template <typename A, typename B> auto mult (A a, B b) { return a * b; } // or template <typename A, typename B> decltype(auto) mult (A a, B b) { return a * b; } auto + decltype + traling return type (can be read as: put here the type decltype would have deduced) Italian C++ Community
i=13 decltype & auto
decltype is an odd creature: it takes an expression (at compile Kme) and gives you a type! But we are taking about C++ so decltype doesn’t follow auto type deducKon rules. const int i = 0; // decltype(i) is an const int struct Point {int x, y;} // decltype(Point::x) is a int decltype(3 + 5.2f) b; // b is a float struct A { int& f(int index) { return v[index]; } vector<int> v; put here the type decltype would have deduced } A e; // x is an int auto x = e.f(); // y is an int& decltype(auto) y = e.f(); Italian C++ Community
i=14 Movability
“Move semanHcs makes it possible for compilers to replace expensive copying operaHons with less expensive moves.” (EMC++) vector<int> getVeryBigVector() { vector<int> r; // fill r with some cool algorithm … return r; } vector<int> mydata = getVeryBigVector(); // C++98 call copy assignment* * Assume no RVO See Marco Arena talk: (CDays 2014 Roma): Italian C++ Community
i=15 Movability: (implicit)
vector<int> getVeryBigVector() { vector<int> r{}; // fill r with some cool algorithm … return r; //implicit std::move temp obj } vector<int> mydata = getVeryBigVector(); // C++11 call move constructor Italian C++ Community
i=16 Movability: in our class
Double free or corrupKon! Italian C++ Community
i=17 Movability: follow the white rabbit
f() HeapContainer<int> (42) HeapContainer<int> x = f(); HeapContainer::(HeapContainer&& rs) x._data f() ; //destroy rs temp x._data is not valid Italian C++ Community
i=18 Movability: in our class
Italian C++ Community
i=19 Movability: std::move & std::forwad
template <typename T> decltype(auto) move (T&& param) { using ReturnType = remove_reference_t<T>&&; return staKc_cast<ReturnType>(param); } template <typename T> T&& forward (remove_reference_t<T>& param) { return staKc_cast<T&&>(param); } Italian C++ Community
Uncondi=onal Cast UncondiKonally casts its argument to an rvalue. Condi=onal Cast Cast to an rvalue only if its argument was iniKalized to an rvalue. i=20 Movability: the swap function
template <typename T> inline void swap(T& a, T& b) { T tmp(a); a = b; b = tmp; } template <typename T> inline void swap(T& a, T& b) { T tmp {std::move(a)}; a = std::move(b); b = std::move(tmp); } 3 copies! L 3 (*) moves! J * Note that for those types that do not implement move semanKcs (that is, do not overload their copy constructor and assignment operator with an rvalue reference version), the new swap behaves just like the old one. Italian C++ Community
i=21 Movability: facts!
Remember: we are discussing C++ … things are not always clear and simple as you can/would expect • 
• 
• 
• 
• 
• 
std::move -­‐> doesn’t move (is an uncondiKonal cast) std::forward -­‐> doesn’t forward (is a condiKonal cast) move is NOT always more cheap then copy! even if you explicit call std::move you can fall-­‐back into a copy type&& doesn’t always represent an rvalue reference std::forward is not perfect! (not all types are correctly forwarded) Italian C++ Community
i=22 Resource Management: Smart Pointers
struct XMLNode {…} vector< XMLNode*> get_nodes(); void do_something (XMLNode*); … for (auto &node : get_node()) do_something (node); Why raw pointer are so bad? 1.  Is not clear who hold the resource 2.  Is not clear which is the exact type of the pointer 3.  Is not clear which funcKon should be used to delete it (delete / delete [] ) 4.  Is difficult to avoid memory leak Italian C++ Community
i=23 Resource Management: Smart Pointers
struct XMLNode {…} vector< shared_ptr<XMLNode>> get_nodes(); void do_something (shared_ptr<XMLNode>); … for (auto &node : get_node()) do_something (node); To avoid this problem C++11 introduces: 1.  std::unique_ptr 2.  std::shared_ptr 3.  std::weak_ptr (not covered here) Italian C++ Community
std::auto_ptr is deprecated!!! i=24 Resource Management: shared_ptr
std::shared_ptr is the “augmented” version of unique_ptr. You can copy it and pass to your funcKons by value or by ref. Roughly we can see shared_ptr as pair of raw pointer and counter, when the counter goes to zero the “correct” destructor is invoked and the memory is released. void set_name(shared_ptr<XMLNode> node); … int main() { auto node = make_shared<XMLNode>(); //node.counter = 1 set_name(node, "body "); // node.counter = 2 //node.counter = 1 } //node.counter = 0 à invoke ~XMLNode() stackoverflow: C++ -­‐ passing references to std::shared_ptr or boost::shared_ptr (by Andrea Bigagli) Italian C++ Community
i=25 Resource Management: unique_ptr
std::unique_ptr embodies exclusive ownership semanKcs always owns what it points to. So copy a unique_ptr is not allowed but you can move it transferring the ownership. A common use of unique_ptr is a factory funcKon (in general for managing resource with exclusive ownership semanKcs). unique_ptr<XMLNode> make_body() { auto node = make_unique<XMLNode>("body"); node-­‐>setAuribute("bgcolor", "#ABAB00"); return node; //implicit move } …. { auto body= make_body(); // do smt with the body here } // destroy body Italian C++ Community
make_unique is part of C++14 but probably your compiler has already implemented it i=26 Lambda Expressions 1/3
•  It’s a simplified notaKon for defining an anonymous funcKon object •  It’s a shorthand to define a functor •  It’s something that generates a closure object [ <capture list> ] (<parameters>) mutable noexcept <return type> { <body> } See my talk: Lambdas Recipes (Italian C++ MeetUp 2014 Milano): hup://www.meocci.it/arKcle/Lambdas_Recipes.pdf Italian C++ Community
i=27 Lambda Expressions 2/3
[ <capture list> ] (<parameters>) mutable noexcept -­‐> <return type> { <body> } •  Capture list: specify the name of local variables that are used in a lambdas (we can specify if they are taken by value, by ref or by move) •  Parameters: the list of parameters taken by lambdas (opKonal) •  An opKonal mutable: a useful way to change internal status of the lambdas •  An opKonal noexcept •  Return type: the type returned by lambdas (almost opKonal*) •  Body: the body of the lambdas (could be any kind of statements) * OpHonal in C++14. OpHonal in C++11 iff the lambdas is composed by one line. Italian C++ Community
i=28 Lambda Expressions 3/3
[] (int a, int b) { return a + b; } struct lambda0 { int operator() (int a, int b) const { return a + b; } } Italian C++ Community
i=29 Lambdas in C++14
 From C++14 new features are introduced: •  We can use generic lambdas: [] (auto x, auto y ) { return x + y; } •  IniKalized lambda capture §  We can use move in capture list: [ v = move (v) ] { /**/ } §  We can define and iniKalize new variable in capture list: [ s = "hello" ] { cout << s << endl; } * note the difference in const retenKon btw [c] or [=] (C++11) and [c=c] (C++14) captures Hint: unKl C++17 don’t use uniform iniKalizaKon syntax inside capture list Italian C++ Community
i=30 Lambdas in STL (as predicate)
#include <algorithm> There are a lot of STL funcKons that accept a callable object and so even lambda: •  std::for_each •  std::count •  std::count_if •  std::find_if •  std::sort vector<int> v{1, 2, 3, 4, 5}; for_each(v.cbegin(), v.cend(), [i = 0] (int n) mutable { cout << i++ << ") val: " << n << endl; }); Italian C++ Community
output 0) val: 1 1) val: 2 2) val: 3 3) val: 4 4) val: 5 i=31 Class Features
• 
• 
• 
• 
• 
DelegaKng Constructor InheriKng Constructors In class member iniKalizer Default & Delete Override & Final Italian C++ Community
i=32 Delegating constructor
class Widget { public: Widget() { init (0, 0); }; Widget(int pos_x, int pos_y) { init (pos_x, pos_y); } virtual void draw() {}; virtual void rotate(float a) {}; void init(int _x, int _y){}; private: int x, y; } If I do not want to duplicate my code I’ve to define a generic (private) init funcKon with an impact on performance See: h`ps://isocpp.org/wiki/faq/ctors#init-­‐lists Italian C++ Community
i=33 Delegating constructor
class Widget { public: Widget() : Widget(0, 0) {}; Widget(int pos_x, int pos_y) : x{pos_x}, y{pos_y} {} virtual void draw() {}; virtual void rotate(float a) {}; virtual ~Widget(){} private: int x, y; } But now we’ve got delegaKng const.!!! Instead of use a generic init funcKon we can delegate the construcKon of our object to a different constructor Pay a`en=on: when the delgaKng constructor concludes his job the object is considered “built & valid” so if the “parent constructor” throw the destructor will be invoked! Italian C++ Community
i=34 Inheriting constructor
class Widget { public: Widget() : Widget(0, 0) {}; Widget(int pos_x, int pos_y) {…} virtual void draw() {}; virtual void rotate(float a) {}; virtual ~Widget(){} private: int x, y; } class Buuon : public Widget { public: Buuon() : Widget(0, 0) {…}; Buuon (int pos_x, int pos_y) : Widget (pos_x, pos_y) {…} void draw() {}; void rotate(float a) {}; private: … } I’ve to overload base Constructor! Italian C++ Community
i=35 Inheriting constructor
class Widget { public: Widget() : Widget(0, 0) {}; Widget(int pos_x, int pos_y) {…} virtual void draw() {}; virtual void rotate(float a) {}; virtual ~Widget(){} private: int x, y; } class Buuon : public Widget { public: using Widget::Widget; void draw() {}; void rotate(float a) {}; private: … } More simple J !!! Italian C++ Community
i=36 default & delete
class Widget { public: Widget() : Widget(0, 0) {}; Widget(int pos_x, int pos_y) {…} Widget(const Widget& rs) = delete; virtual void draw() {}; virtual void rotate(float a) {}; virtual ~Widget() = default; private: int x, y; } In C++11 we can ask the compiler to generate or delete some special funcKons: •  constructors, •  destructor, •  copy assignment operators •  move assignment operators. Italian C++ Community
i=37 default & delete
class Widget { public: Widget() : Widget(0, 0) {}; Widget(int pos_x, int pos_y) {…} Widget(const Widget& rs) = delete; virtual void draw() {}; virtual void rotate(float a) {}; virtual ~Widget() = default; private: int x, y; } Isn’t safe to copy an object via base class so disable Copy Constructor! (use a virtual clone funcKon instead) Generate a public inline virtual destructor Italian C++ Community
i=38 override & final
void Widget::rotate(float a) { cout << "Widget::rotate" << endl; } class Buuon : public Widget { public: … virtual void draw() {} virtual void rotate(double a) { cout << "Buuon::rotate" << endl; } } Compile sure … but is not what we expect! { Buuon b; Widget& r = b; r.rotate(45.0f); } // output: Widget::rotate Italian C++ Community
i=39 override & final
void Widget::rotate(float a) { cout << "Widget::rotate" << endl; } class Buuon : public Widget { public: … virtual void draw() {} virtual void rotate(double a) override { cout << "Buuon::rotate" << endl; } } Now doesn’t compile! Italian C++ Community
i=40 override & final
struct GenIDPolicy { virtual int generate_id() { … } } class Widget : public GenIDPolicy { virtual int generate_id() final { … } … }; class Buuon : public Widget { public: virtual void draw() override {} virtual void rotate(float a) override {} int generate_id() { /* new policy */ } } final instead is used to prevent overriding of a method of member base class. We can define an enKre class as final. error: overriding final funcKon ‘virtual int Widget::generate_id()’ Italian C++ Community
i=41 Tuple & Tie
A classical design problem in C++ is: How I can return more than one value from my funcKon? Consider this example: class Student { public: bool getCompleteName(srKng& o_name, string& o_surname) const; … } Student s(…); string name, surname; s.getCompleteName(name, surname); Italian C++ Community
i=42 Tuple & Tie
But since C++11 we’ve tuple & Ke into the standard! std::=e permits us to easily unpack a tuple to its arguments or instances of std::ignore class Student { public: tuple<string, string> getCompleteName() const; … } Student s(...); // I’ve to define name & surname before to use Ke string name, surname; =e(name, surname) = s.getCompleteName(); Italian C++ Community
i=43 Threads
Afer several years C++ has got: Threads, Memory Model and Async Task. During these years we’ve seen: •  pthread •  boost::thread •  CWinThread •  QThread •  … Italian C++ Community
i=44 Threads: basics
std::thread th ([]{ cout << "I’m a thread! " << endl; }); th.join(); void th_body(int n) { cout << "The answer is always: " << n; } std::thread th2 (th_body, 42); th2.detach(); We can define the body of the thread in place using lambdas In general we can use any callable object Note: thread’s constructor always copying arguments Italian C++ Community
i=45 Threads: an example
We want to count how many prime numbers are present in a vector. We can use this simple serial algorithm: // load data vector<unsigned int> v(10000); // fill data with a sequence of posiKve number generate (v.begin(), v.end(), [n=0]() mutable {return n++;}); // then compute auto r = count_if (v.cbegin(), v.cend(), [](const auto& e){ return is_prime(e); }); cout << “Result: " << r << endl; Italian C++ Community
i=46 Threads: an example
Or we can do in parallel! 0 1 2 3 4 … Italian C++ Community
n i=47 Threads: async
We can simplify our code using std::async. This funcKon create an “asynchronous” task and return a future to propagate the results of computaKon. Italian C++ Community
i=48 More Advanced
•  Variadic Template: a template with support for an infinite list of parameters •  constexpr: indicates a value that it’s known during compilaKon •  noexcept(expr): a new auribute for a funcKon that (essenKally) say “this funcKon doesn’t throw iff expr is true” Italian C++ Community
i=49 C++11: a concrete example
struct Point {int x, y;}; auto& f = Singleton<Point>::emplace(1, 5); auto& p = Singleton<Point>::getInstance(); cout << f.x << ", " << f.y << endl; Italian C++ Community
i=50 Do you remember our ZIP function?
Let me introduce the zip func=on. This funcKon takes two list and pairs elements from the first list with the elements from the second list. Our goal is to implement it in C++11! zip :: [a] -­‐> [b] -­‐> [(a, b)] zip _ [] = [] zip [] _ = [] zip (x:xs) (y:ys) = (x, y) : zip xs ys Haskell ImplementaKon 1 2 3 4 5 6 A B C ZIP 1, A 2, B 3, C Thanks to lisperaK.com Italian C++ Community
i=51 ZIP function in C++11
Now using C++14! • 
• 
Haskell & other fun.lang. has tail call opHmizaHon, in C++ is not always true so: recursive -­‐> iteraKve If possible prefer a std::algorithm to everything else! Italian C++ Community
i=52 What's next in C++17?
• 
• 
• 
• 
• 
• 
• 
• 
• 
• 
Concept N4174, Call syntax: x.f(y) vs. f(x,y) N4165 Unified Call Syntax D4128, Eric Nibler Range v3 lib. N4332, Networking library N3858, Resumable FuncKons N4230, nested namespace definiKons like namespace A::B::C { } N3922, which fixes the most common piƒall with auto and {}, so that auto x{y}; Some cleanup! (auto_ptr, trigraph, bind1...) and much more… I hope to see more & more funcHonal programming stuff in C++17 !!! Italian C++ Community
i=53 C++17: Which features would you like to be in?
Convincetemi ad usare il C++14 (Roberto Beuazzoni), C++ MeetUp Bologna 2014 Italian C++ Community
i=54 Some books
• 
• 
• 
• 
• 
Tour of C++, Bjarne Stroustrup The C++ Programming Language 4th ediKon, Bjarne Stroustrup EffecKve Modern C++, Scou Meyers The C++ Standard Library: A Tutorial and Reference (2nd), Nicolai M. Josu…s C++11 Rocks, Alex Korban Italian C++ Community
i=55 Some videos
(in english) • 
• 
• 
• 
• 
• 
Make Simple Tasks Simple, CPPCon 2014 -­‐ Bjarne Stroustrup Back to the Basics EssenKals of Modern C++ Style, CPPCon 2014 -­‐ Herb Suuer An EffecKve C++11 & C++14, GoingNaKve 2013 -­‐ Scou Meyers C++ Seasoning, GoingNaKve 2013 -­‐ Sean Parent EffecKve C++, NDC2014 -­‐ Scou Meyers Type DeducKon and Why You Care, CPPCon 2014 -­‐ Scou Meyers (in italian) •  Il nuovo C++. Torniamo alle basi, Community Days 2014 – Marco Arena Italian C++ Community
i=56 www.italiancpp.org i=57 About Me!
Soˆware Engineer @ Commprove (Firenze) C++ (C++11/14), JavaScript, PHP5, HTML5/CSS3, Python, Java7 [email protected]
http://www.meocci.it
https://github.com/meox
Preferred OS: Linux especially Debian Linux Preferred PL: C++11/14 Preferred IDE: Sublime Text 3 & vim Italian C++ Community
Haskell newbie i=58