Your SlideShare is downloading. ×
  • Like
Effective Code Transformations in C++
Upcoming SlideShare
Loading in...5
×

Thanks for flagging this SlideShare!

Oops! An error has occurred.

×

Now you can save presentations on your phone or tablet

Available for both IPhone and Android

Text the download link to your phone

Standard text messaging rates apply

Effective Code Transformations in C++

  • 2,775 views
Published

Slide del talk presentato il 30 Novembre 2013 all'Italian Agile Day a Reggio Emilia (Marco Arena & Paolo Polce)

Slide del talk presentato il 30 Novembre 2013 all'Italian Agile Day a Reggio Emilia (Marco Arena & Paolo Polce)

Published in Technology , Sports
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
2,775
On SlideShare
0
From Embeds
0
Number of Embeds
7

Actions

Shares
Downloads
20
Comments
0
Likes
3

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Effective Code Transformations in C++ Marco Arena Paolo Polce marco@italiancpp.org paolo@webshell.it Reggio Emilia, 30 Novembre 2013
  • 2. Italian C++ Community www.italiancpp.org @italiancpp 2
  • 3. Ancora evolvono il C++??! 3
  • 4. When I hear they’re adding features to C++ This PLT Life - http://this-plt-life.tumblr.com/ 4
  • 5. Outline • C++11, benvenuto nel team! – C++98  C++11 & snippet C# • Il team cambia stile & coding standards – Design patterns – Multi-threaded C++ • Alcune linee guida 5
  • 6. Outline • C++11, benvenuto nel team! – C++98  C++11 & snippet C# • Il team cambia stile & coding standards – Design patterns – Multi-threaded C++ • Alcune linee guida 6
  • 7. C++ o C#?! var dati = new List<int>(){1,2,3,4,5}; 7
  • 8. C++ o C#?! var dati = new List<int>(){1,2,3,4,5}; auto dati = vector<int>{1,2,3,4,5}; 8
  • 9. auto // C++98 vector<int> vec (10); vector<int>::iterator it = vec.begin();
  • 10. auto // C++98 vector<int> vec (10); vector<int>::iterator it = vec.begin(); it 10 1 2 3 4 12 6 it 5 7 11 13 10
  • 11. auto // C++98 vector<int> vec (10); vector<int>::iterator it = vec.begin(); // C++11 vector<int> vec (10); auto it = vec.begin();
  • 12. auto // C++98 vector< pair<string, int> > cards = ... ; vector< pair<string, int> >::iterator it = cards.begin(); 12
  • 13. auto // C++98 vector< pair<string, int> > cards = ... ; vector< pair<string, int> >::iterator it = cards.begin(); // C++11 auto it = cards.begin(); 13
  • 14. range-based iteration // C++98 for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) { cout << *it << " "; } 14
  • 15. range-based iteration // C++11 for (auto i : vec) { cout << i << " "; } 15
  • 16. range-based iteration // C++11 for (auto i : vec) { cout << i << " "; } for (const auto& i : vec) { cout << i << " "; } 16
  • 17. range-based iteration C++98 C++11 for ( vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) { cout << *it << " "; } for (auto i : vec) { cout << i << " "; } C# foreach (var i in arrayList) { System.Console.Write(i); } 17
  • 18. lambdas & algorithms // C++98 vector<int>::const_iterator find_in_range(const vector<int>& vec) { vector<int>::const_iterator i = vec.begin(); for( ; i != vec.end(); ++i ) { if( *i > 0 && *i < 10 ) break; } return i; } 18
  • 19. lambdas & algorithms // C++98 bool elem_in_range(int elem) { return elem > 0 && elem < 10; } vector<int>::const_iterator it = find_if (vec.begin(), vec.end(), elem_in_range); 19
  • 20. lambdas & algorithms // C++11 auto it = find_if (begin(vec), end(vec), [](int i) { return i > 0 && i < 10; }); 20
  • 21. lambdas & algorithms // C++14 auto it = find_if (begin(vec), end(vec), [](auto i) { return i > 0 && i < 10; }); 21
  • 22. lambdas & algorithms C++14 [](auto i) { return i > 0 && i < 10; } C# (int i) => i > 0 && i < 10; 22
  • 23. C++ o C#?! var dati = new List<int>(){1,2,3,4,5}; auto dati = vector<int>{1,2,3,4,5}; 23
  • 24. initializer lists // C++98 int arr[] = {1,2,3,4,5}; vector<int> data; data.push_back(1); data.push_back(2); ... vector<int> data (arr, arr + 5); 24
  • 25. initializer lists // C++98 int arr[] = {1,2,3,4,5}; vector<int> data (arr, arr + 5); // C++11 vector<int> data = {1,2,3,4,5}; // oppure (auto-everything syntax): auto data = vector<int>{1,2,3,4,5}; 25
  • 26. initializer lists C++98 C++11 vector<int> data; data.push_back(1); data.push_back(2); data.push_back(3); ... auto data = vector<int>{1,2,3,4,5}; C# var dati = new List<int>() {1, 2, 3, 4, 5}; 26
  • 27. smart pointers // C++98 { Car* car = new Car(...); ... car->Move(); ... delete car; } 27
  • 28. smart pointers // C++98 { Car* car = new Car(...); ... car->Move(); throw exception(…) ... delete car; } 28
  • 29. smart pointers // C++98 Car *car = NULL; try { car = new Car(...); car->Move(); delete car; } catch(...) { delete car; ASSERT(FALSE); LOG(ERROR) << "critical"; throw; } 29
  • 30. smart pointers // C++98 catch(...) { delete car; ASSERT(FALSE); LOG(ERROR) << "critical"; throw; } 30
  • 31. smart pointers { // C++11 unique_ptr<Car> car {new Car{arg1}}; ... car->Move(); ... } // delete automatico // C++14 auto car = make_unique<Car>(arg1) 31
  • 32. Outline • C++11, benvenuto nel team! – C++98  C++11 & snippet C# • Il team cambia stile & coding standards – Design patterns – Multi-threaded C++ • Alcune linee guida 32
  • 33. Modern C++: Factory // C++98 IWriter* Create(...) { ... return new CoutWriter(...); } // chiamante: IWriter* writer = Create (...); ... delete writer; 33
  • 34. Modern C++: Factory // C++11 unique_ptr<IWriter> Create (...) { ... return unique_ptr<IWriter>(new CoutWriter(...)); } // chiamante: auto writer = Create(...); 34
  • 35. Modern C++: Factory // C++98 class WriterFactory { public: IWriter* Create(const string& where) { if (where == "cout") return new CoutWriter(); if (where == "dbgview") return new DbgViewWriter(); if (where == " null") return new NullWriter(); throw exception("where to write?"); } }; 35
  • 36. Modern C++: Factory // C++11-14 class WriterFactory { public: unique_ptr<IWriter> Create(const string& where) { static map<string, function<unique_ptr<IWriter>()>> m = { {"cout", []{return make_unique<CoutWriter>()}}, {"dbgview", []{return make_unique<DbgViewWriter>()}}, {"null", []{return make_unique<NullWriter>()}} }; return m.at(where)(); // può sollevare eccezione // oppure una policy diversa } 36 };
  • 37. Modern C++: RAII & DEFER bool FileExists(const char* path) { ifstream file{path}; // file.open() return file.is_open(); } // file.close() automatico 37
  • 38. Modern C++: RAII & DEFER void SomeFuntion() { ... Anything ... Log("SomeFunction executed"); } 38
  • 39. Modern C++: RAII & DEFER void SomeFuntion() { ... Anything ... throw exception(…) Log("SomeFunction executed"); } 39
  • 40. Modern C++: RAII & DEFER // go style func SomeFuntion() { defer func() { Log("SomeFunction executed") } ... Anything ... } 40
  • 41. Modern C++: RAII & DEFER void SomeFuntion() { defer d{ []{ Log("SomeFunction executed"); }}; ... Anything ... } 41
  • 42. Modern C++: RAII & DEFER class defer { function<void()> m_toExec; public: defer(function<void()> f) : m_toExec{f} { } ~defer() { m_toExec(); } }; Qui una versione migliore e completa: http://www.italiancpp.org/2013/07/16/defer-con-raii-lambda/ 42
  • 43. Modern C++: RAII & DEFER Live Demo git clone https://ilpropheta@bitbucket.org/ilpropheta/iad2013.git main.cpp: DeferTest 43
  • 44. Outline • C++11, benvenuto nel team! – C++98  C++11 & snippet C# • Il team cambia stile & coding standards – Design patterns – Multi-threaded C++ • Alcune linee guida 44
  • 45. Multi-Threaded C++ int main() { vector<int> vec(100000); iota(begin(vec), end(vec), 0); // 0 1 2 3 4 ... int avg = 0; thread t1 { [&]{ avg = accumulate(begin(vec), end(vec), 0)/vec.size(); }}; auto maxEl = max_element(begin(vec), end(vec)); t1.join(); cout << "max: " << *maxEl << endl; cout << "avg: " << avg << endl; } 45
  • 46. Multi-Threaded C++ Live Demo git clone https://ilpropheta@bitbucket.org/ilpropheta/iad2013.git main.cpp: ThreadTest 46
  • 47. Multi-Threaded C++ int main() { vector<int> vec(100000); iota(begin(vec), end(vec), 0); auto willbeAvg = async ( [&]{ return accumulate(begin(vec), end(vec), 0)/vec.size(); }}; cout << "max: " << *max_element(begin(vec), end(vec)) << endl; cout << "avg: " << willbeAvg.get() << endl; } 47
  • 48. Multi-Threaded C++ Live Demo git clone https://ilpropheta@bitbucket.org/ilpropheta/iad2013.git main.cpp: FutureTest 48
  • 49. Multi-Threaded C++ future promise get() v set_value(v) Thread 1 Thread 2 49
  • 50. Multi-Threaded C++ Live Demo git clone https://ilpropheta@bitbucket.org/ilpropheta/iad2013.git main.cpp: PromiseTest 50
  • 51. Multi-Threaded C++: PPL void vector_mult(vector<double>& v, double c) { for_each( begin(v), end(v), [&](double& n) { n *= c; } ); } 51
  • 52. Multi-Threaded C++: PPL #include <ppl.h> using namespace Concurrency; void vector_mult(vector<double>& v, double c) { parallel_for_each( begin(v), end(v), [&](double& n) { n *= c; } ); } 52
  • 53. Multi-Threaded C++: PPL Live Demo git clone https://ilpropheta@bitbucket.org/ilpropheta/iad2013.git PPLSesame.cpp 53
  • 54. Outline • C++11, benvenuto nel team! – C++98  C++11 & snippet C# • Il team cambia stile & coding standards – Design patterns – Multi-threaded C++ • Alcune linee guida 54
  • 55. Alcune linee guida • Devo migrare tutto subito? – No, intanto assicurati di cosa supporta il tuo compilatore. – Inizia migrando le cose deprecate (e.g. auto_ptr). – Aggiungi qualche test su quello che stai modificando. – Vale sempre il principio del boyscout… 55
  • 56. Alcune linee guida • Il mio compilatore non supporta alcune feature del C++11. Che devo fare? – Se puoi, pianifica una migrazione del compilatore. – Individua cosa potrà beneficiare del C++11 e come lo riscriveresti. – Metti dei reminder per quando migrerai, tipo: //TO-DO-CPP11: … 56
  • 57. Alcune linee guida • Il miglior consiglio per usare C++11/C++14? – Provalo! – Il materiale di qualità sul C++ è aumentato. – Frequenta isocpp.org – Frequenta italiancpp.org  57
  • 58. Marco & Paolo Marco Arena marco@italiancpp.org http://marcoarena.wordpress.com Paolo Polce paolo@webshell.it @paolopolce webshell.it agileworks.it 58
  • 59. ~talk() noexcept { answer_questions(); } 59
  • 60. ~talk() noexcept { answer_questions(); } Quanto è nerd questa slide? 60
  • 61. Grazie! 61
  • 62. Bonus: non-member begin/end // C++98 vector<int>::iterator it = vec.begin(); int arr[] = {1,2,3,4,5}; arr.begin(); // eh ??? // C++11 auto it = begin(vec); auto it = begin(arr); // ok! 62
  • 63. Bonus: make_unique (1) // C++14 auto car = make_unique<Car>(arg1) • auto-everything syntax • Exception-safety: void func(unique_ptr<Car> c1, unique_ptr<Car> c2); func(unique_ptr<Car>{new Car{}}, unique_ptr<Car>{new Car{}}); • Le istruzioni per creare i due Car* possono essere riordinate dal compilatore. 63
  • 64. Bonus: make_unique (2) func(unique_ptr<Car>{new Car{}}, unique_ptr<Car>{new Car{}}); Esempio di possibile esecuzione: 1. Allocazione memoria per la prima Car 2. Allocazione memoria per la seconda Car 3. Costruzione prima Car 4. Costruzione seconda Car 5. Costruzione primo unique_ptr 6. Costruzione secondo unique_ptr Che succede se 4 tira un’eccezione? Memory leak della prima Car! Se chiamiamo due funzioni (come make_unique), il compilatore è costretto a fare 1,2,5 insieme e poi 3,4,6! Più dettagli a questo link (Sutter) 64