network virtualization based on effective packet transformations
Effective Code Transformations in C++
-
Upload
marco-arena -
Category
Technology
-
view
2.995 -
download
4
description
Transcript of Effective Code Transformations in C++
Effective Code Transformations in C++
Marco [email protected]
Paolo [email protected]
Reggio Emilia, 30 Novembre 2013
2
Italian C++ Community
www.italiancpp.org
@italiancpp
3
Ancora evolvono il C++??!
4
This PLT Life - http://this-plt-life.tumblr.com/
When I hear they’re adding features to C++
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
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
7
C++ o C#?!
var dati = new List<int>(){1,2,3,4,5};
8
C++ o C#?!
var dati = new List<int>(){1,2,3,4,5};auto dati = vector<int>{1,2,3,4,5};
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();
1 2 3 4
it
10
6 12
5 7 11 13
it
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();
13
auto
// C++98
vector< pair<string, int> > cards = ... ;vector< pair<string, int> >::iterator it = cards.begin();
// C++11
auto it = cards.begin();
14
range-based iteration
// C++98
for (vector<int>::iterator it = vec.begin(); it != vec.end(); ++it)
{ cout << *it << " ";}
15
range-based iteration
// C++11
for (auto i : vec){
cout << i << " ";}
16
range-based iteration
// C++11
for (auto i : vec){
cout << i << " ";}
for (const auto& i : vec){
cout << i << " ";}
17
range-based iterationC++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); }
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;
}
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);
20
lambdas & algorithms
// C++11
auto it = find_if (begin(vec), end(vec), [](int i) {
return i > 0 && i < 10;});
21
lambdas & algorithms
// C++14
auto it = find_if (begin(vec), end(vec), [](auto i) {
return i > 0 && i < 10;});
22
lambdas & algorithmsC++14
[](auto i) { return i > 0 && i < 10; }
C#
(int i) => i > 0 && i < 10;
23
C++ o C#?!
var dati = new List<int>(){1,2,3,4,5};auto dati = vector<int>{1,2,3,4,5};
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);
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};
26
initializer listsC++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};
27
smart pointers
// C++98{ Car* car = new Car(...); ... car->Move(); ... delete car;}
28
smart pointers
// C++98{ Car* car = new Car(...); ... car->Move(); ... delete car;}
throw exception(…)
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;
}
30
smart pointers// C++98
catch(...) { delete car;
ASSERT(FALSE);LOG(ERROR) << "critical";
throw; }
31
smart pointers
{ // C++11 unique_ptr<Car> car {new Car{arg1}}; ... car->Move(); ...
} // delete automatico
// C++14auto car = make_unique<Car>(arg1)
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
33
Modern C++: Factory
// C++98
IWriter* Create(...){
...return new CoutWriter(...);
}
// chiamante:
IWriter* writer = Create (...);...delete writer;
34
Modern C++: Factory
// C++11
unique_ptr<IWriter> Create (...){
...return unique_ptr<IWriter>(new
CoutWriter(...));}
// chiamante:
auto writer = Create(...);
35
Modern C++: Factory// C++98class 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?");
}};
36
Modern C++: Factory// C++11-14class 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 }};
37
Modern C++: RAII & DEFER
bool FileExists(const char* path){
ifstream file{path}; // file.open()
return file.is_open();} // file.close() automatico
38
Modern C++: RAII & DEFERvoid SomeFuntion(){
... Anything ...
Log("SomeFunction executed");}
39
Modern C++: RAII & DEFERvoid SomeFuntion(){
... Anything ...
Log("SomeFunction executed");}
throw exception(…)
40
Modern C++: RAII & DEFER
// go stylefunc SomeFuntion(){
defer func() {Log("SomeFunction executed")
}... Anything ...
}
41
Modern C++: RAII & DEFER
void SomeFuntion(){
defer d{ []{ Log("SomeFunction executed");
}};... Anything ...
}
42
Modern C++: RAII & DEFERclass 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/
43
Modern C++: RAII & DEFER
Live Demogit clone https://[email protected]/ilpropheta/iad2013.git
main.cpp: DeferTest
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
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;
}
46
Multi-Threaded C++
Live Demogit clone https://[email protected]/ilpropheta/iad2013.git
main.cpp: ThreadTest
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;}
48
Multi-Threaded C++
Live Demogit clone https://[email protected]/ilpropheta/iad2013.git
main.cpp: FutureTest
49
Multi-Threaded C++
future promise
Thread 1 Thread 2
v set_value(v)
get()
50
Multi-Threaded C++
Live Demogit clone https://[email protected]/ilpropheta/iad2013.git
main.cpp: PromiseTest
51
Multi-Threaded C++: PPL
void vector_mult(vector<double>& v, double c){
for_each( begin(v), end(v),[&](double& n) {
n *= c;}
);}
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;}
);}
53
Multi-Threaded C++: PPL
Live Demogit clone https://[email protected]/ilpropheta/iad2013.git
PPLSesame.cpp
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
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…
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: …
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
58
Marco & Paolo
Marco [email protected]://marcoarena.wordpress.com
Paolo [email protected]@paolopolce
webshell.it agileworks.it
59
~talk() noexcept {
answer_questions();}
60
~talk() noexcept {
answer_questions();}
Quanto è nerd questa slide?
61
Grazie!
62
Bonus: non-member begin/end
// C++98vector<int>::iterator it = vec.begin();int arr[] = {1,2,3,4,5}; arr.begin(); // eh ???
// C++11auto it = begin(vec);auto it = begin(arr); // ok!
63
Bonus: make_unique (1)
// C++14auto 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.
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 Car2. Allocazione memoria per la seconda Car3. Costruzione prima Car4. Costruzione seconda Car5. Costruzione primo unique_ptr6. 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)