elements of c++11

115
@Uilian Ries 02 / 2016 https://goo.gl/ U0fZJa The Elements of C+ +11

Upload: uilian-ries

Post on 19-Mar-2017

197 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Elements of C++11

@Uilian Ries

02 / 2016

https://goo.gl/U0fZJaThe Elements of C++11

Page 2: Elements of C++11

AGENDA •Why should I learn about C++11?•C++11 Features

•deduction of a type from an initializer•the type of an expression•Initializer-list and uniform initialization•rvalue references and move semantics•static assertions

•preventing exception propagation•override controls•scoped and strongly typed enums•lambda expressions•defaulted and deleted functions•smart pointers•standard container array

Page 3: Elements of C++11

WHY SHOULD I LEARN ABOUT C++11?

fonte: https://isocpp.org/files/img/wg21-timeline.png

Page 4: Elements of C++11

WHY SHOULD I LEARN ABOUT C++11?“C++11 feels like a new language” - Bjarne Stroustrup

Page 5: Elements of C++11

DEDUCTION OF A TYPE FROM AN INITIALIZER

// C++98std::map<std::string, std::vector<int, int> >::iterator it = foo.begin();Singleton& singleton = Singleton::instance();int bar;

// C++11auto it = std::begin(foo);auto& singleton = Singleton::instance();

auto bar; // error: declaration has no initializerauto bar = 0;

Page 6: Elements of C++11

DEDUCTION OF A TYPE FROM AN INITIALIZER

// C++98std::vector<std::string>::const_iterator it;for (it = strings.begin(); it != strings.end(); ++it) { /*...*/ }

// C++11for (auto it : strings) { /*...*/ }

Page 7: Elements of C++11

DEDUCTION OF A TYPE FROM AN INITIALIZER// C++11auto sum(int a, int b) -> int { return a + b;}

template<typename Builder>void buildAndProcess(Builder& builder){ auto baz = builder.Build(); baz.work();}

Page 8: Elements of C++11

DEDUCTION OF A TYPE FROM AN INITIALIZER// C++11template<typename Builder>auto buildAndProcess(Builder& builder) -> ??? { auto baz = builder.Build(); baz.work(); return baz;}

Page 9: Elements of C++11

THE TYPE OF AN EXPRESSION•decltype

•Auto lets you declare a variable with a particular type• decltype lets you extract the type from a variable (or any other expression)

Page 10: Elements of C++11

THE TYPE OF AN EXPRESSION// C++11int bar = 42;decltype(bar) qux = bar;

auto qux = bar; // same

int qux();decltype(qux()); // int

Page 11: Elements of C++11

DEDUCTION OF A TYPE FROM AN INITIALIZER// C++11template<typename Builder>auto buildAndProcess(Builder& builder) -> decltype( builder.Build() ){ auto baz = builder.Build(); baz.work(); return baz;}// C++14template<typename Builder>auto buildAndProcess(Builder& builder){ auto baz = builder.Build(); baz.work(); return baz;}

Page 12: Elements of C++11

DEDUCTION OF A TYPE FROM AN INITIALIZER#include <iostream>struct Foo { Foo () { std::cout << 1; } ~Foo() { std::cout << 3; } void print() { std::cout << 2; }};

int main() { Foo foo[3]; for (auto it : foo) { it.print(); } return 0;}

fonte: http://ideone.com/ux5CeG for (auto& it : foo) { it.print(); }

Page 13: Elements of C++11

DEDUCTION OF A TYPE FROM AN INITIALIZER// C++11int& bar();

auto foo = bar(); // int or int& ?

/* auto defaults to being by-value for references */

auto& foo = bar(); // int&

int* foo = new int(5);auto bar = foo; // bar is int*

auto* qux = foo; // as before

Page 14: Elements of C++11

DEDUCTION OF A TYPE FROM AN INITIALIZERstd::string foo("foo");unsigned size = foo.size(); // type shortcut

std::string::size_type size = foo.size(); // official return type

auto size = foo.size(); // correct deduction

Page 15: Elements of C++11

DEDUCTION OF A TYPE FROM AN INITIALIZER// C++11#include <unordered_map>std::unordered_map<std::string, std::string> bar;// bar receives some elements ...for (const std::pair<std::string, std::string>& it : bar) { /* ... */ }

for (const auto& it : bar) { /* ... */ }

Page 16: Elements of C++11

DEDUCTION OF A TYPE FROM AN INITIALIZER•Things to remember:

•auto must be initialized;•the compiler can evaluates better than you;•auto can simplify your expression;•a function can return auto type;•a function parameter can be auto type (C++14);•auto defaults to being by-value for references.

Page 17: Elements of C++11

INITIALIZER-LIST AND UNIFORM INITIALIZATION// C++98int foo[] = {16,2,77,29};std::vector<int> bar(foo, foo + sizeof(foo) / sizeof(foo[0]));// C++98std::map<int, bool> qux;qux[100] = true;qux[110] = false;

// C++11std::vector<int> bar = {16,2,77,29};// C++11std::map<int, bool> qux = {{100, true}, {110, false}};

Page 18: Elements of C++11

INITIALIZER-LIST AND UNIFORM INITIALIZATION#include <iostream>#include <initializer_list>

struct Foo {Foo(int a, int b) { std::cout << a << " " << b <<

std::endl; }Foo (std::initializer_list<int> list) {

for (auto it : list) { std::cout << it << std::endl; }}

};

int main() { Foo foo{1, 2}; Foo foobar(1, 2); return 0;}

Page 19: Elements of C++11

INITIALIZER-LIST AND UNIFORM INITIALIZATION// C++98int foo = 5.2; // narrowing convertionint bar(3.14); // narrowing convertion

// C++11int foo{5.2}; // error: narrowing convertionint qux[3]{1, 2, 3};std::vector<char> baz{'a', 'b', 'c'};

// C++98Baz::Baz(int bar, int corge) : bar_(bar), corge_(corge) {}insert_vlan( vlan(100, TAGGED) );

// C++11Baz::Baz(int bar, int corge) : bar_{bar}, corge_{corge} {}insert_vlan( {100, TAGGED} );

Page 20: Elements of C++11

INITIALIZER-LIST AND UNIFORM INITIALIZATION•initializer-list

•array of objects of type const T;•must be homogeneous;•immutable sequence.

std::initializer_list<int> qux{1, 2, 3, 4, 5}; // Okay

std::initializer_list<int> qux{1, 2, 3.0, 4, 5}; // NOK!error: narrowing conversion of '3.0e+0' from 'double' to 'int' inside { } [-Wnarrowing]

std::initializer_list<int> qux{1, 2, 3, 4, 5};*qux.begin() = 42;

error: assignment of read-only location

Page 21: Elements of C++11

INITIALIZER-LIST AND UNIFORM INITIALIZATION#include <iostream>#include <type_traits>

int main() { auto foo{5}; auto bar = {3, 5}; auto qux{4, 2}; std::cout << std::is_integral<decltype(foo)>::value; std::cout << std::is_integral<decltype(bat)>::value; std::cout << std::is_integral<decltype(qux)>::value; return 0;}

fonte: http://ideone.com/QMhxvv

auto foo = 5;

error: direct-list-initialization of 'auto'

requires exactly one element [-

fpermissive] auto qux{4, 2};

Page 22: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•In C++11, there are rvalues and lvalues:

•lvalues is an expression that could be the left hand side of an assignment;•rvalues is an expression that could be the right hand side of an assignment;

int foo = 42; // foo is a lvalue; 42 is an rvalue

Page 23: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•References:

•lvalue reference is formed by placing an & after some type;•rvalue reference is formed by placing an && after some type;

int bar = 42; // bar is a lvalueint& bar_ref = bar; // bar_ref is a lvalue referenceint& baz = 42; // error: can't bind rvalueconst int& baz = 42; // okay! baz is const referenceint&& qux = 42; // qux is an rvalue referencequx = 54; // okay! can replaceint&& corge = bar; // error: can't bind lvalue

Page 24: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•Why would we want to do this?:

•move semantics;•perfect forward;

Page 25: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•Move semantics

•replaces expansive copy with less expansive move;•enables the creation of move-only type as unique_ptr;

•Consider:

template <class T>swap(T& a, T& b){ T tmp(a); // now we have two copies of a a = b; // now we have two copies of b b = tmp; // now we have two copies of tmp (aka a)}

Page 26: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS#include <utility>

template <class T>swap(T& a, T& b){ T tmp(std::move(a)); // move a contents to tmp; a is empty a = std::move(b); // move b contents to a; b is empty b = std::move(tmp); // move tmp contents to b; tmp is empty}

•move gives its target the value of its argument, but is not obliged to preserve the value of its source;•if move is not possible, then the value will be copied.

Page 27: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICSclass Foo { // Temporary Object

std::string bar;public:

Foo(const std::string& ss) : bar(ss) {assert(!bar.empty()); // ss was copied!

}};

int main() {std::string baz("F00B4R");Foo foo(baz);

assert(!baz.empty()); // baz is no more necessary!return 0;

}http://ideone.com/fzZHCB

Page 28: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS#include <utility> // Temporary Object

class Foo {std::string bar;

public:Foo(std::string&& ss) : bar(std::move(ss)) {

assert(!bar.empty()); // ss was moved!}

};int main() {

std::string baz("F00B4R");Foo foo(std::move(baz));

assert(baz.empty()); // baz was moved!return 0;

}http://ideone.com/fzZHCB

Page 29: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•About move and forward functions

•move doesn’t move;•forward doesn’t forward;•neither does anything at runtime;•generate nothing.

Page 30: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•About move and forward functions

•move and forward are functions that performs casts;•move is a unconditional cast to an rvalue;•forward performs this cast only if a particular condition is fulfilled.

template<typename T>typename remove_reference<T>::type&&move(T&& param){ using ReturnType = typename remove_reference<T>::type&&; return static_cast<ReturnType>(param);}

•move returns a && type (rvalue reference);•remove_reference ensures that && is applied only to non-reference.

Page 31: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•Perfect Forward

•write function templates that take arbitrary arguments;•forward exactly the same arguments as were passed.

•Consider:

template <class T>std::shared_ptr<T>factory(){ return std::make_shared<T>();}

Page 32: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICStemplate <class T, class Arg>std::shared_ptr<T>factory(Arg& arg){ return std::make_shared<T>(arg);}

int main() {std::string ss("FOO");auto foo = factory<std::string>(ss);auto bar = factory<std::string>(std::move(ss)); // error!return 0;

}

Page 33: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICStemplate <class T, class Args>std::shared_ptr<T>factory(Args&& args){ return std::make_shared<T>(std::forward<Args>(args));}

•forward preserves the lvalue/rvalue-ness of the argument that was passed to factory;•Args&& can be anything.

Page 34: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•Things to remember•move can be cheaper than copy;•std::move doesn’t move; it’s an unconditional cast to an rvalue;•std::forward doesn’t forward; it’s casts its argument to an rvalue only if that argument is bound to an rvalue;

Page 35: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•Universal References

•sometimes && is not a rvalue reference.

class Foo{};// ...Foo&& foo = Foo(); // && means rvalue reference

auto&& bar = foo; // && doesn't mean rvalue reference

template<typename T>void process(std::vector<T>&& args); // && means rvalue reference

template<typename T>void process(T&& args); // && doesn't mean rvalue reference

Page 36: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•Universal References

•can binds rvalue reference;•can binds lvalue reference;•can binds const or non-consts objects.

class Foo{};// ...Foo&& foo = Foo(); // we can obtain the address of foo

auto&& bar = foo; // so, bar is a reference to a lvalue

Foo& bar = foo; // same

Page 37: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•Universal References

template<typename T>void process(T&& args) {}

process(10); // 10 is a rvalue; T&& is a rvalue reference

Foo foo;process(foo); // foo is a lvalue; T&& is a lvalue reference, as Foo&

template <typename T>void foobar(const T&& param) {} // const qualifier disables uref

Page 38: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•Universal References

•use move on rvalue references and forward on universal references;

class Foo {std::string bar;public:template <typename T>void set_bar(T&& t) { bar = std::move(t); }

};int main() {

std::string baz{"F00B4R"};Foo foo;foo.set_bar(baz);assert(!baz.empty()); // Ops!return 0;

}http://ideone.com/MXdPXx

Page 39: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•Universal References

•use move on rvalue references and forward on universal references;

class Foo {std::string bar;public:void set_bar(std::string&& ss) { bar = std::move(ss); }

};int main() {

std::string baz{"F00B4R"};Foo foo;foo.set_bar(baz); // error: no mathing function assert(!baz.empty());return 0;

}http://ideone.com/WFlcon

Page 40: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•Things to remember: Universal References

•auto&& and T&& for a deduces type T, are universal reference;•universal references are lvalue references when initialized with lvalues;•universal references are rvalue references when initialized with rvalues;•use move on rvalue references;•use forward on universal references.

Page 41: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•Consider pass by value when cheaper: Overloading

class Foo {std::vector<std::string> foobar;

public:void insert(const std::string& ss) {

foobar.push_back(ss); // Copy!}void insert(std::string&& ss) {

foobar.push_back(std::move(ss));}

};int main() {

Foo foo;std::string bar("B4R");foo.insert(bar); // insert by lvaluefoo.insert("F00"); // insert by rvaluereturn 0;

} // http://ideone.com/Qb3ASJ

Page 42: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•Consider pass by value when cheaper: Universal Reference

class Foo {std::vector<std::string> foobar;

public:template <typename T>void insert(T&& ss) {

foobar.push_back(std::forward<T>(ss));}

};int main() {

Foo foo;std::string bar("B4R");foo.insert(bar); // insert by lvaluefoo.insert("F00"); // insert by rvaluereturn 0;

}http://ideone.com/EPmSho

Page 43: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•Consider pass by value when cheaper: Passing by value

class Foo {std::vector<std::string> foobar;

public:void insert(std::string ss) {

foobar.push_back(std::move(ss));}

};int main() {

Foo foo;std::string bar("B4R");foo.insert(bar); // insert by lvaluefoo.insert("F00"); // insert by rvaluereturn 0;

}http://ideone.com/c1Hsv7

Page 44: Elements of C++11

RVALUE REFERENCES AND MOVE SEMANTICS•Overloading

•one copy for lvalues;•one move for rvalues.

•Universal Reference•one copy for lvalues;•one move for rvalues.

•Passing by value•one copy + one move for lvalues;•two moves for rvalues;+ parameters that are always copied;+ nearly efficient as pass by reference;+ easier to implement;+ can generate less object code.

Page 45: Elements of C++11

STATIC ASSERTIONS● static_assert performs compile time assertion checking.

static_assert ( bool_constexpr , message );

#include <type_traits>int main() {

constexpr int* baz = nullptr;/* ... */static_assert(baz, "Ops! Null pointer");return 0;

}// http://ideone.com/JNF9sZ

Page 46: Elements of C++11

STATIC ASSERTIONS#if sizeof(unsigned) >= 8# error "64-bit arch is not supported"#endifint main() { return 0; }

#include <type_traits>static_assert(sizeof(unsigned) >= 8, "64-bit arch is not supported");

int main() { return 0; }

error: static assertion failed: 64-bit arch is not

supported// http://ideone.com/OmYixS

Page 47: Elements of C++11

STATIC ASSERTIONS#include <type_traits>template <typename T>void foobar() {

static_assert(std::is_copy_constructible<T>::value, "Type T must be copyable");}

struct Foo { Foo(const Foo&) = delete; };

int main() {foobar<Foo>();return 0;

}error: static assertion failed: Type T must be copyable// http://ideone.com/DxRSnI

Page 48: Elements of C++11

STATIC ASSERTIONS•Things to remember:

•the compiler evaluates the expression;•it cannot be used to check assumptions that depends on run-time values.

Page 49: Elements of C++11

PREVENTING EXCEPTION PROPAGATION// C++98 - no exceptionsvoid foo() throw(){}

•callers might be dependent on the original exception;•if the exception specification is violated, then the call stack is unwound to to foo’s caller.

Page 50: Elements of C++11

PREVENTING EXCEPTION PROPAGATION// C++11void bar() noexcept{}

•the stack is only possibly unwound before program execution is terminated;•So, optimizers need not keep the runtime stack in an unwindable state.•it permits compilers to generate better object code!

Page 51: Elements of C++11

PREVENTING EXCEPTION PROPAGATION// C++11 - cannot throw an exception void foo() noexcept { }

// as beforevoid bar() noexcept(true) { }

// permit exceptions to propagatevoid qux() noexcept(false) { }

Page 52: Elements of C++11

PREVENTING EXCEPTION PROPAGATION// C++11 - can throw if is not copy constructibletemplate <typename T>void foo(T t) noexcept(std::is_nothrow_copy_constructible<T>::value) { }

// C++11 - evaluate expressiontemplate<typename T>void foo(T t) {}

template<typename T>void foobar(T t) noexcept(noexcept(foo(t))){ foo(t);}

Page 53: Elements of C++11

PREVENTING EXCEPTION PROPAGATION•Things to remember:

•‘noexcept’ is simply a shorthand for noexcept(true);•noexcept(false) specifies that it does permit exceptions to propagate;•Use noexcept instead of the exception specifier throw, which is deprecated in C++11 and later;• noexcept enables compilers to generate more efficient code;•noexcept is particularly valuable for the move operations, swap, memory deallocation functions, and destructors;•apply noexcept to a function when you are sure it will never allow an exception to propagate up the call stack.

Page 54: Elements of C++11

OVERRIDE CONTROLS•Rules for override

•The base class function must be virtual;•The base and derived function names must be identical (except in the case of destructors);•The parameter types of the base and derived functions must be identical;•The constness of the base and derived functions must be identical;•The return types and exception specifications of the base and derived functions must be compatible.

•C++11 adds one more:•The functions’ reference qualifiers must be identical.

Page 55: Elements of C++11

OVERRIDE CONTROLS#include <iostream>

class Qux {public:

void work() & { std::cout << 1; }void work() && { std::cout << 2; } static Qux makeQux() { return Qux{}; }

};

int main() {Qux::makeQux().work();auto qux = Qux{};qux.work();return 0;

}fonte: http://ideone.com/EO5YdS

Page 56: Elements of C++11

OVERRIDE CONTROLSclass Foo {public: virtual void func1() const; virtual void func2(int i); virtual void func3() &; void func4() const;};

class Bar : public Foo {public: virtual void func1(); virtual void func2(unsigned int i); virtual void func3() &&; void func4();};

Page 57: Elements of C++11

OVERRIDE CONTROLSclass Foo {public: virtual void func1() const; virtual void func2(int i); virtual void func3() &; void func4() const;};

class Bar : public Foo {public: virtual void func1() override; virtual void func2(unsigned int i) override; virtual void func3() && override; void func4() override;};fonte: http://ideone.com/VjZiaB

Page 58: Elements of C++11

SCOPED AND STRONGLY TYPED ENUMSThe enum classes ("new enums", "strong enums") address three problems with traditional C++ enumerations:

Conventional enums implicitly convert to int, causing errors when someone does not want an enumeration to act as an integer;

Conventional enums export their enumerators to the surrounding scope, causing name clashes.

The underlying type of an enum cannot be specified, causing confusion, compatibility problems, and makes forward declaration impossible.

from: http://www.stroustrup.com/C++11FAQ.html#enum

Page 59: Elements of C++11

SCOPED AND STRONGLY TYPED ENUMS// C++98 - unscoped enums.enum Status { OK, ERROR = 100, INVALID, UNKNOWN = 0xFFFF };int status = ERROR;

enum Device { UNKNOWN, PRINTER, KEYBOARD };// error: redeclaration of ‘UNKNOWN’

// C++11 - scoped enums.enum class Status { OK, ERROR = 100, INVALID, UNKNOWN };enum class Device { PRINTER, KEYBOARD, UNKNOWN = 0xFFFF };auto status = UNKNOWN; // error: ‘UNKNOWN’ was not declared in this scope

auto status = Status::UNKNOWN;

Page 60: Elements of C++11

SCOPED AND STRONGLY TYPED ENUMS// C++11 - Specify the underlying type #include <iostream>enum class Signal : char { YES = 'Y', NO = 'N' };

int main() { char signal = Signal::YES; std::cout << signal << std::endl; return 0;}

error: cannot convert ‘Signal’ to ‘char’ in initialization

auto signal = static_cast<char>(Signal::YES);

Page 61: Elements of C++11

SCOPED AND STRONGLY TYPED ENUMS// C++11 - Specify the underlying type #include <iostream>enum class Signal : char;

void foo(Signal signal) { std::cout << static_cast<char>(signal) << std::endl;}

enum class Signal : char { YES = 'Y', NO = 'N' };

int main() { auto signal = Signal::YES; foo(signal); return 0;}

Page 62: Elements of C++11

LAMBDA EXPRESSIONtemplate<typename T>void show(const T& t) {

std::cout << t << std::endl;}

int main() {std::vector<std::string> bar{"FOO", "BAR", "QUX"};std::for_each(bar.begin(), bar.end(),

show<decltype(bar)::value_type>);return 0;

}

http://ideone.com/U69PEI

Page 63: Elements of C++11

LAMBDA EXPRESSION•About lambda function

•inline anonymous functor;• specify a simple action to be performed by some function;•similiar to the idea of a functor or function pointer;•can use std::function as wrapper.

•Syntax

[ capture-list ] ( params ) -> return-type { body }

Page 64: Elements of C++11

LAMBDA EXPRESSION#include <string>#include <vector>#include <algorithm>#include <iostream>

int main() {

std::vector<std::string> bar{"FOO", "BAR", "QUX"};std::for_each(bar.begin(), bar.end(), [ ] (const std::string& ss) {

std::cout << ss << std::endl;});

return 0;}http://ideone.com/TvxZIy

Page 65: Elements of C++11

LAMBDA EXPRESSIONusing Bar = std::function<double(double, double)>;

int main() {auto foo = []() { std::cout << "FOO" << std::endl; };foo();

Bar bar = [] (double a, double b) -> double { return a * b; };std::cout << bar(5, 2) << std::endl;

std::string ss{"F00B4R"};[] () { std::cout << ss << std::endl; };

return 0;}http://ideone.com/2iU3rc

Page 66: Elements of C++11

LAMBDA EXPRESSION•Capture List

[ ] Capture nothing (or, a scorched earth strategy?)[&] Capture any referenced variable by reference[=] Capture any referenced variable by making a copy[=, &foo] Capture any referenced variable by making a copy, but capture variable foo by reference[bar] Capture bar by making a copy; don't copy anything else[this] Capture the this pointer of the enclosing class

Page 67: Elements of C++11

LAMBDA EXPRESSION// C++14#include <cassert>auto foo(auto bar) {

return bar * 2;}

int main() {auto baz = [](auto qux) { return qux * 2; };assert(foo(1));assert(baz(2));return 0;

}

http://ideone.com/kjnUme

Page 68: Elements of C++11

LAMBDA EXPRESSION•Things to remember:

•avoid capture any referenced variable by reference (dangling ref);• Lambdas are more readable, more expressive, and may be more efficient than using std::bind.

Page 69: Elements of C++11

DEFAULTED AND DELETED FUNCTIONSstruct Bar {};struct Baz { Bar* bar; };

int main() {Baz baz{new Bar{}};Baz bazfoo = baz; // bazfoo copy from baz!return 0;

}

•Prohibiting copying idiom:•Use boost::noncopyable.•Declare copy constructor as private

Page 70: Elements of C++11

DEFAULTED AND DELETED FUNCTIONSstruct Bar {};struct Baz { Bar* bar; Baz(const Baz&) = delete; // disallow copy constructor};

int main() {Baz baz{new Bar{}};Baz bazfoo = baz; // error: use of deleted function return 0;

}

Page 71: Elements of C++11

DEFAULTED AND DELETED FUNCTIONSstruct BigNumber {

BigNumber(long long) {}BigNumber(int) = delete;

};

int main(){

BigNumber(5ll);BigNumber(42); // deleted functionreturn 0;

}

Page 72: Elements of C++11

DEFAULTED AND DELETED FUNCTIONS•What are the special member functions of C++11?

•Default constructor C::C();•Destructor C::~C();•Copy constructor C::C (const C&);•Copy assignment C& operator= (const C&);•Move constructor C::C (C&&);•Move assignment C& operator= (C&&);

Page 73: Elements of C++11

DEFAULTED AND DELETED FUNCTIONSSpecial Member Function Implicity defined Default definition

Default constructor if no other constructors does nothing

Destructor if no destructor does nothing

Copy Contructor if no move constructor and no move assignment

copies all members

Copy Assignment if no move constructor and no move assignment

copies all members

Move Constructor if no destructor, no copy constructor and no copy nor move assignment

moves all members

Move Assignment if no destructor, no copy constructor and no copy nor move assignment

moves all members

Page 74: Elements of C++11

DEFAULTED AND DELETED FUNCTIONS#include <utility>#include <string>#include <cassert>struct Foo { std::string ss; Foo(const Foo& foo) : ss{foo.ss} {} Foo(std::string&& s) : ss{std::move(s)} {}};

int main() {Foo foo{"FOO"};Foo foobar(std::move(foo));assert(foo.ss.empty());return 0;

}http://ideone.com/fzZHCB

Page 75: Elements of C++11

DEFAULTED AND DELETED FUNCTIONS#include <utility>#include <string>#include <cassert>struct Foo { std::string ss; Foo(const Foo&) = default; // explicitly defaulted Foo(Foo&&) = default; // explicitly defaulted Foo(std::string&& s) : ss{std::move(s)} {}};int main() {

Foo foo{"FOO"};Foo foobar(std::move(foo));assert(foo.ss.empty());return 0;

} // http://ideone.com/0Ir7rG

Page 76: Elements of C++11

SMART POINTERS•RAII (Resouce Acquisition Is Initialization)

•Programming technique which binds the life cycle of a resource to the lifetime of an object with automatic storage duration;•Scope-Bound Resource Management (SBRM);

•RAII - Summary•encapsulate each resource into a class, where the constructor acquires the resource and establishes all class invariants or throws an exception if that cannot be done, the destructor releases the resource and never throws exceptions;

•always use the resource via an instance of a RAII-class that either has automatic storage duration, is a non-static member of a class whose instance has automatic storage duration.

Page 77: Elements of C++11

SMART POINTERS#include <mutex>

void consummer() { mutex.lock(); auto worker = work_queue.front(); work_queue.pop(); worker(); // Ops! throw exception mutex.unlock();}

Page 78: Elements of C++11

SMART POINTERS#include <mutex>

void consummer() { std::lock_guard<std::mutex> lock(mutex) // Safe! Using RAII auto worker = work_queue.front(); work_queue.pop(); worker(); // throw exception. mutex will be unlocked }

Page 79: Elements of C++11

SMART POINTERS•Look and feel like pointers, but are smarter

•an object that owns another object and manages that other object through a pointer;•support pointer operations like dereferencing (operator *) and indirection (operator ->);•Automatic cleanup;•Automatic initialization;•Exception safety;

Page 80: Elements of C++11

SMART POINTERStemplate<typename T>class SmartPointer { T* t_; public: SmartPointer(T* t = 0) : t_(t) {} ~SmartPointer() { delete t_; } T& operator* () { return *t_; } T* operator-> () { return t_; }};

int main() { SmartPointer<std::string> smartPointer(new std::string("bar")); std::cout << *smartPointer << std::endl; std::cout << smartPointer->size() << std::endl; return 0;}

Page 81: Elements of C++11

SMART POINTERS

•auto_ptr // C++98•unique_ptr // C++11•shared_ptr // C++11•weak_ptr // C++11

Page 82: Elements of C++11

SMART POINTERS - AUTO_PTR// C++98#include <iostream>#include <memory>

int main() {

std::auto_ptr<int> foo(new int(1)); std::auto_ptr<int> foobar = foo; // foo will be null

std::cout << *foobar << std::endl; std::cout << *foo << std::endl; // undefined behavior

return 0;}

Page 83: Elements of C++11

SMART POINTERS - UNIQUE_PTR// C++11#include <iostream>#include <memory>

int main() {

std::unique_ptr<int> foo(new int(1)); std::unique_ptr<int> foobar = foo;

std::cout << *foobar << std::endl; std::cout << *foo << std::endl;

return 0;}

error: use of deleted function

std::unique_ptr<int> foobar = foo;

Page 84: Elements of C++11

SMART POINTERS - UNIQUE_PTRclass DevicePort {

std::string intf_name;DevicePort(std::string&& name) : intf_name{std::move(name)} {}

public:static DevicePort* Create(std::string&& ss) {

return new DevicePort(std::move(ss));}void connect() throw (std::runtime_error) {

if (intf_name.find("gigabit") == std::string::npos) {throw std::runtime_error("Could not connect!");

} else { /* ... */ }}

}; int main() {

auto port_gb = DevicePort::Create("megabit-ethernet");try {

port_gb->connect();delete port_gb;

} catch (const std::runtime_error& err) { std::cerr << err.what() << std::endl;

}return 0;

}

Page 85: Elements of C++11

SMART POINTERS - UNIQUE_PTR

// #include <...>template <typename T, typename ...Ts>std::unique_ptr<T> Factory(Ts&& ...ts) {

return std::unique_ptr<T>(new T(std::forward<Ts>(ts))...);} struct DevicePort {

std::string intf_name;DevicePort(std::string&& name) : intf_name{std::move(name)}

{}}; int main() {

auto port_gb = Factory<DevicePort>("gigabit-ethernet");std::cout << port_gb->intf_name << std::endl;return 0;

} http://ideone.com/ZLxOHR

Page 86: Elements of C++11

SMART POINTERS - UNIQUE_PTR

#include <iostream>#include <memory>#include <functional>

struct Bar {~Bar() { std::cout << 2; }static void deleter(Bar*) { std::cout << 1; }

}; int main() {

using bar_delete = std::function<void(Bar*)>;auto bar = std::unique_ptr<Bar, bar_delete>(

new Bar(), Bar::deleter);return 0;

}http://ideone.com/8VTUEe

Page 87: Elements of C++11

SMART POINTERS - UNIQUE_PTR

•Things to remember:•strict ownership;•not copyable;•moveable;•deletes using an associated deleter;•exception safety;•can be stored in containers;•return allocated pointer by function.

Page 88: Elements of C++11

SMART POINTERS - SHARED_PTR

#include <iostream>#include <memory>

struct Foo {};struct Bar { std::shared_ptr<Foo> foo; };struct Baz { std::shared_ptr<Foo> foo; };

int main() {auto foo = std::make_shared<Foo>();Bar bar{ foo };Baz baz{ foo };std::cout << foo.use_count() << std::endl; // 3return 0;

}http://ideone.com/hAaNjY

Page 89: Elements of C++11

SMART POINTERS - SHARED_PTR

#include <memory>#include <string>

int main() {

auto foobar = new std::string{"F00B4R"};

std::shared_ptr<std::string> foo(foobar);

std::shared_ptr<std::string> bar(foobar);

return 0;}

http://ideone.com/eqeJGp

Page 90: Elements of C++11

SMART POINTERS - SHARED_PTR

https://goo.gl/qDu9SL

Page 91: Elements of C++11

SMART POINTERS - SHARED_PTR

•Things to remember:•shared ownership;•copyable;•moveable;•deletes using an associated deleter;•exception safety;•can be stored in containers;•return allocated pointer by function;•there is control block;•avoid create shared_ptr from variables of raw pointers.

Page 92: Elements of C++11

SMART POINTERS - WEAK_PTR

struct Port;

struct Aggregation { std::list<std::shared_ptr<Port>> children; };

struct Port { std::shared_ptr<Aggregation> parent; };

int main() { auto aggregation = std::make_shared<Aggregation>(); auto ports = { std::make_shared<Port>(), std::make_shared<Port>() };

aggregation->children = ports; for (auto& port : aggregation->children) { port->parent = aggregation; } return 0;}// http://ideone.com/YldGSH

Page 93: Elements of C++11

SMART POINTERS - WEAK_PTR

struct Port;

struct Aggregation { std::list<std::shared_ptr<Port>> children; };

struct Port { std::weak_ptr<Aggregation> parent; };

int main() { auto aggregation = std::make_shared<Aggregation>(); auto ports = { std::make_shared<Port>(), std::make_shared<Port>() };

aggregation->children = ports; for (auto& port : aggregation->children) { port->parent = aggregation; } return 0;}// http://ideone.com/fKq2hr

Page 94: Elements of C++11

SMART POINTERS - WEAK_PTR

template<typename T>void show(T& t) { std::cout << (t.lock() ? 0 : 1); }

int main() {std::weak_ptr<std::string> bar;

{auto foo = std::make_shared<std::string>("F00B4R");bar = foo;show(bar);

}show(bar);return 0;

}// http://ideone.com/uE7kJ9

Page 95: Elements of C++11

SMART POINTERS - WEAK_PTR

•Things to remember:•wraps a weakly linked pointer;•models temporary ownership;•break 'circular references' with shared_ptr;•would be a cache;•solve the dangling pointer problem.

Page 96: Elements of C++11

STANDARD CONTAINER ARRAY

“like a built-in array without the problems” - bjarne

// C++98static const size_t BUFFER_SIZE = 20;unsigned buffer [BUFFER_SIZE] = {};

// C++11#include <array>

constexpr auto BUFFER_SIZE = 20;std::array<unsigned, BUFFER_SIZE> buffer;

Page 97: Elements of C++11

STANDARD CONTAINER ARRAY

// C++11#include <array>std::array<int, 5> foo;

auto foobar = foo[3]; // foobar is zero. Default elements are zero

auto* bar = foo; // error: std::array doesn't implicitly convert to a pointer

auto* bar = foo.data(); // okay!

unsigned baz [] = { 1, 2, 4, 8, 16, 32 };

std::array<unsigned> qux = { 1, 2, 4, 8, 16, 32 };// error: wrong number of template arguments

Page 98: Elements of C++11

STANDARD CONTAINER ARRAY

template <class T> typename T::value_type sum(const T& t){ return std::accumulate(t.begin(), t.end(), 0);}int main() { std::vector<unsigned> foo = { 1, 2, 4, 8 }; auto bar = sum(foo); // bar is 15

unsigned qux [] = { 1, 2, 4, 8 }; bar = sum(qux); // error: no matching function for call

std::array<unsigned, 4> baz = { 1, 2, 4, 8 }; bar = sum(baz); // bar is 15 return 0;} // http://ideone.com/IAksgE

Page 99: Elements of C++11

EXAMPLE - CODE 1

struct foobar {std::map<std::string, std::string> bar;std::vector<foobar> qux;

foobar() : bar{{"F00", "B4R"}} {}

~foobar() { bar.clear(); qux.clear(); }};

int main() {foobar f;f.bar["QUX"] = "C0U5&";return 0;

}

Page 100: Elements of C++11

EXAMPLE - CODE 1

#include <map>#include <vector>#include <iostream>

struct foobar {std::map<std::string, std::string> bar = {{"F00", "B4R"}};std::vector<foobar> qux;

};

int main() {foobar f;f.bar["QUX"] = "C0U5&";

return 0;}

Page 101: Elements of C++11

EXAMPLE - CODE 2

struct foobar {std::vector<unsigned> qux;void foo() {

int bar; int i;for (i = 0; i < (int) qux.size(); i++) {

bar = qux.at(i); std::cout << bar << std::endl;

}}

};int main() {

foobar bar;bar.qux.push_back(42);bar.foo();return 0;

}

Page 102: Elements of C++11

EXAMPLE - CODE 2

struct foobar {std::vector<unsigned> qux;void foo() {

for (const auto& it : qux) { std::cout << it << std::endl;

}}

};

int main() {foobar bar;bar.qux.emplace_back(42);bar.foo();return 0;

}

Page 103: Elements of C++11

EXAMPLE - CODE 3

struct Foo {std::string foobar;Foo(std::string&& ss) : foobar{std::move(ss)} {}

template <typename String>static std::unique_ptr<Foo> Factory(String&& ss) {

return std::unique_ptr<Foo>(new Foo(std::forward<String>(ss)));

}};

int main() {auto foo = Foo::Factory("F00B4R");std::cout << foo->foobar << std::endl;return 0;

} // http://ideone.com/dhZTRF

Page 104: Elements of C++11

CONSTANT EXPRESSIONS

•Use constexpr whenever possible

•Objects: const + value known during compilation.

•Functions: return constexpr result if called with constexpr args.

Page 105: Elements of C++11

CONSTANT EXPRESSIONS

•constexpr objects

constexpr auto foo = 42; // Okay!

constexpr auto bar = foo; // Okay!

bar = 11; // error: assignment of read-only variable 'bar'

std::array<unsigned, foo> qux; // Okay!

static_assert(foo == 42, "Foo must be 42!"); // Okay!

int size = 42;constexpr auto foobar = size; // error: the value of 'size' is not usable in a constant expression

Page 106: Elements of C++11

CONSTANT EXPRESSIONS

•constexpr objects vs const objects

int bar = 42;const auto foo = bar; // okay: may be initialized at runtime

std::array<unsigned, foo> qux; // error: foo is not a constant expression

•All constexpr objects are const, but not all const objects are constexpr.•If you need compile-time value, then constexpr is the proper tool.

Page 107: Elements of C++11

CONSTANT EXPRESSIONS

•constexpr objects vs const objects

int bar = 42;const auto foo = bar; // okay: may be initialized at runtime

std::array<unsigned, foo> qux; // error: foo is not a constant expression

•All constexpr objects are const, but not all const objects are constexpr.•If you need compile-time value, then constexpr is the proper tool.

Page 108: Elements of C++11

CONSTANT EXPRESSIONS

•constexpr objects rules:•may any literal type including:

•float point types•char literals•pointer literals•literal obejcts

•requires no storage declaration•constexpr parameters not allowed:

void foo(constexpr int bar) // error: could not be constexpr{

std::array<int, bar> qux;}

Page 109: Elements of C++11

CONSTANT EXPRESSIONS

•constexpr functions:•execute during compile-time, and return constexpr, only:

•the arguments are constexpr•the result is used in constexpr context

•execute (perphaps not) during compile-time, when:•the arguments are constexpr•the result is not used in constexpr context

•execute at run-time when there is 1 or more non-constexpr arguments.

•no need to overload,•constexpr function take both constexpr and non-constexpr args.

Page 110: Elements of C++11

CONSTANT EXPRESSIONS

constexpr int half_of(double value) noexcept { return value / 2; }

int main() { constexpr auto foo = half_of(42); // compile-time call static_assert(foo == 21, "Ops!"); auto bar = half_of(12); // runtime call assert(bar == 6); const auto foobar = half_of(12); // compile-time call static_assert(foobar == 6, "Ops!"); auto qux = 74; auto couse = half_of(qux); // runtime call assert(couse == 37); return 0;}

Page 111: Elements of C++11

CONSTANT EXPRESSIONS

•constexpr functions rules:•its return type shall be a literal type; and•its parameter types shall be literal types; and•its function-body shall be a compound-statement of the form: { return expression; }

where expression is a potential constant expression; and

•every implicit conversion used in converting expression to the function return type shall be one of those allowed in a constant expression.•constexpr functions and constexpr constructors are implicitly inline •a constexpr function shall not be virtual

Page 112: Elements of C++11

CONSTANT EXPRESSIONS

•constexpr functions:

constexpr int square(int x) { return x * x; } // OK

constexpr long long_max() { return 2147483647; } // OKconstexpr int abs(int x) { return x < 0 ? -x : x; } // OKconstexpr void f(int x) { /* ... */ } // error: return type is voidconstexpr int prev(int x) { return --x; } // error: use of decrement

constexpr int g(int x, int n) { int r = 1; // error: body not just “return expr’’ while (--n > 0) r *= x; return r;}

Page 113: Elements of C++11

CONSTANT EXPRESSIONS

•Relaxed constexpr restrictions C++14:

•any declaration, except:•static•thread_local

•conditional branching statements if and switch;•any looping statement, including range-based for;•change the value of an object if the lifetime of that object began within the constant expression function;

constexpr int pow(int base, int exp) noexcept { auto result = 1; for (int i = 0; i < exp; ++i) result *= base; return result;}

Page 114: Elements of C++11

CONSTANT EXPRESSIONS

•Things to remember:

•constexpr objects are const and are initialized with values known during compilation.

•constexpr functions can produce compile-time results when called with

arguments whose values are known during compilation.

•constexpr objects and functions may be used in a wider range of contexts than non-constexpr objects and functions.

•constexpr is part of an object’s or function’s interface.

Page 115: Elements of C++11

THE ELEMENTS OF C++11

•How to improve my skills:

•books:•more effective c++ and modern effective c++; Scott Meyers•a tour of C++; bjarne stormtrooper

•web•https://isocpp.org/•http://scottmeyers.blogspot.com/•http://herbsutter.com/•http://erdani.com/•http://cppcon.org/•http://cppcast.com/