C++11 features
==============



Auto and decltype
=================


template<class T>
void printall(const vector<T>& v)
{
  for (typename vector<T>::const_iterator p = v.begin(); p!=v.end(); ++p)
     cout << *p << "\n";
}


template<class T>
void printall(const vector<T>& v)
{
  for (auto p = v.begin(); p!=v.end(); ++p)
     cout << *p << "\n";
}


When the type of a variable depends critically on template argument it can
be really hard to write code without auto. For example:


template<class T, class U>
void (const vector<T>& vt, const vector<U>& vu)
{
  // ...
  auto tmp = vt[i]*vu[i];
  // ...
}



decltype(E) is the type ("declared type") of the name or expression E
and can be used in declarations. For example:


void f(const vector<int>& a, vector<float>& b)
{
  typedef decltype(a[0]*b[0]) Tmp;

  for (int i=0; i<b.size(); ++i)
  {
    Tmp* p = new Tmp(a[i]*b[i]);
    // ...
  }
  // ...
}


Auto and decltype:


template <class T, class S>
auto max(T t, S s) -> decltype(t+s)
{
  if ( t > s )
    return t;
  else
    return s;
}



Range for
=========


A range for statement allows you to iterate through a "range",
which is anything you can iterate through like an STL-sequence
defined by a begin() and end(). All standard containers can be
used as a range, as can a std::string, an initializer list, an
array, and anything for which you define begin() and end(), e.g.
an istream. For example:


void f(const vector<double>& v)
{
  for (auto x : v) cout << x << '\n';
  for (auto& x : v) ++x;  // using a reference to allow us to chage the value
}


You can read that as "for all x in v" going through starting with
v.begin() and iterating to v.end(). Another example:


for (const auto x : { 1,2,3,5,8,13,21,34 }) cout << x << '\n';


The begin() and end() can be a member to be called x.begin()
or a free-standing function to be called begin(x).


// What about this?
void f(Node n_, const std::vector<std::vector<Node>>& parents_)
{
  Node n = n_;

  // do something with n...

  for ( Node n : parents_[n] )
  {
    // ...
  }
}




Default and delete functions
============================


class X
{
  // ...
  X& operator=(const X&) = delete;      // Disallow copying
  X(const X&) = delete;
};


Conversely, we can also say explicitly that we want to default
copy behavior:


class Y
{
  // ...
  Y& operator=(const Y&) = default;     // default copy semantics
  Y(const Y&) = default;
};




Constans expressions
====================


enum Flags { good=0, fail=1, bad=2, eof=4 };

constexpr int operator|(Flags f1, Flags f2) { return Flags(int(f1)|int(f2)); }

void f(Flags x)
{
  switch (x)
  {
  case bad:         /* ... */ break;
  case eof:         /* ... */ break;
  case bad|eof:     /* ... */ break;
  default:          /* ... */ break;
  }
}



Initializer list
================


vector<double> v = { 1, 2, 3.456, 99.99 };

list<pair<string,string>> languages =
{
  {"Nygaard","Simula"}, {"Richards","BCPL"}, {"Ritchie","C"}
};

map<vector<string>,vector<int>> years =
{
  { {"Maurice","Vincent", "Wilkes"},{1913, 1945, 1951, 1967, 2000} },
  { {"Martin", "Ritchards"} {1982, 2003, 2007} },
  { {"David", "John", "Wheeler"}, {1927, 1947, 1951, 2004} }
};




Delegating constructors
=======================


In C++98, if you want two constructors to do
the same thing, repeat yourself or call "an init() function." For example:


class X
{
  int a;
  validate(int x) { if (0<x && x<=max) a=x; else throw bad_X(x); }
public:
  X(int x) { validate(x); }
  X() { validate(42); }
  X(string s) { int x = lexical_cast<int>(s); validate(x); }
  // ...
};


Verbosity hinders readability and repetition is error-prone.
Both get in the way of maintainability. So, in C++11, we can
define one constructor in terms of another:


class X
{
  int a;
public:
   X(int x) { if (0<x && x<=max) a=x; else throw bad_X(x); }
   X() :X{42} { }
   X(string s) : X{lexical_cast<int>(s)} { }
   // ...
};




Move semantics
==============

Based mostly on Thomas Becker's article
http://thbecker.net/articles/rvalue_references/section_01.html 


What is the rvalue reference and why we need it?
I many earlier languages assignment works in the following way:

  <variable> := <expression>

like

  x := y + 5;


In C/C++ however there might be expressions on the left side of =

  <expression> = <expression>

like

  *++p = *++q;  // likely ok if p is pointer, except p is const *


But not all kind of expressions may appear on the left hand side:

  y + 5 = x;  // likely error except some funny operator+


"Left value" is originated to C language: an l value is an expression
that may appear on the left hand side of an assignment. "Right value"
is anything else.

Basically left-value identified a writeable memory location in C.
In C++ this is a bit more complex, but here is a widely acecpted
definition:


An "lvalue" is an expression that refers to a memory location and allows
us to take the address of that memory location via the & operator.
An "rvalue" is an expression that is not an "lvalue"



These are lvalues:

int  i = 42;
int &j = i;
int *p = &i;

 i = 99;
 j = 88;
*p = 77;

int *fp() { return &i; } // returns pointer to i: lvalue
int &fr() { return i; }  // returns reference to i: lvalue

*fp() = 66;  // i = 66
 fr() = 55;  // i = 55 


These are rvalues:

int f() { int k = i; return k; } // returns rvalue

  i = f();  // ok
  p = &f(); // bad: can't take address of rvalue
f() = i;    // bad: can't use rvalue on lefthand side


A rigorous definition of lvalue and rvalue:
http://accu.org/index.php/journals/227



C and C++ has value semantics -- when we use assignment we copy by default.


Array a, b, c, d, e;

a = b + c + d + e;


This will generate the following pseudo-code:


// pseudocode for a = b + c + d + e

double* _t1 = new double[N];
for ( int i=0; i<N; ++i)
    _t1[i] = b[i] + c[i];

double* _t2 = new double[N];
for ( int i=0; i<N; ++i)
    _t2[i] = _t1[i] + d[i];

double* _t3 = new double[N];
for ( int i=0; i<N; ++i)
    _t3[i] = _t2[i] + e[i];

for ( int i=0; i<N; ++i)
    a[i] = _t3[i];

delete [] _t3;
delete [] _t2;
delete [] _t1;



Performace problems

- For small arrays new  and delete result poor performance: 1/10 of C.
- For medium arrays, overhead of extra loops and memory access add +50%
- For large arrays, the cost of the temporaries are the limitations

This has been investigated by Todd Veldhuizen and has led to C++ template
metaprogramming and expression templates.


It would be nice not to create the temporaries, but steal the resources of
the arguments of operator+()

But!

We can destroy only the temporaries: we should keep the original resources
for the b, c, d, e variables. How can we distinguis between variables and
unnamed temporaries? --> overloading

Overloading --> We need a separate type!
What kind of requirements we have for this type?

1. should be a reference type - otherwise we gain nothing

2. if there is an overload between ordinary reference and this new type
   then rvalues should prefer the new type and lvalues the ordinary reference


Rvalue reference:

X &&


Old kind of references now are called as lvalue references:

X &


void f(X&  arg_)  // lvalue reference parameter
void f(X&& arg_)  // rvalue reference parameter


X x;
X g();

f(x);   // lvalue argument --> f(X&)      
f(g()); // rvalue argument --> f(X&&)



We can overload copy constructor and assignmnet operator overloads:


class X
{
public:
  X(const X& rhs);
  X(X&& rhs);

  X& operator=(const X& rhs);
  X& operator=(X&& rhs);
private:


};


X& X::operator=(const X& rhs)
{
  // free old resources than copy resource from rhs
  return *this;
}

X& X::operator=(X&& rhs)  // draft version, will be revised later
{
  // free old resources than move resource from rhs
  // leave rhs in a destructable state
  return *this;
}


Reverse compatibility

If we implement the old-style memberfunctions with lvalue reference parameters
but do not implement the evalue reference overloading versions we keep the
old behaviour -> we can gradually move to move semantics.

However, if we implement "only" the rvalue operations than we cannot call
these on lvalues -> no default lvalue-copy constructor or operator= will be generated.



Issues


First Amendment to the C++ Standard quoted by Thomas Becker:
http://thbecker.net/articles/rvalue_references/section_04.html  

"The committee shall make no rule that prevents C++ programmers from 
shooting themselves in the foot." 


template<class T>
void swap(T&& a, T&& b)
{
  T tmp(a);
  a = b;
  b = tmp;
}

X a, b;
:
swap(a, b);




Correct way:


template<class T>
void swap(T& a, T& b)
{
  T tmp(std::move(a));
  a = std::move(b);
  b = std::move(tmp);
}

X a, b;
:
swap(a, b);



X&& f();

void g(X&& arg_)
{
  X var1 = arg_;   // copy or move?     
  X var2 = f();    // copy or move?
}


Since arg_ is declared as rvalue reference we might think that here
X::X(X&& rhs) will be called. But not always:

Things that are declared as rvalue reference can be lvalues or rvalues.
Anything has a "name" is an "lvalue" otherwise it is an "rvalue".

Therefore in the var1 example above X::X(const X& will be called),
and in the var2 example X::X(&&) is called.

Philosophy:
After X var1 = arg_; arg_ is still in scope and can be available.


X&& f();

void g(X&& arg_)
{
  X var1 = arg_;   // copy  X::X(const X&)
  X var2 = f();    // move  X::X(X&&)
}                  // arg_ goes out of scope here



If-it-has-a-name-rule:


class Base
{
public:
  Base(const Base& rhs); // non-move semantics
  Base(Base&& rhs);      // move semantics      
  :
};


class Derived : public Base
{
  Derived(const Derived& rhs);  // non-move semantics
  Derived(Derived&& rhs);       // move semantics
  :
};


Derived(Derived const & rhs) : Base(rhs)  // copy semantics
{
  // Derived-specific stuff
}

// wrong
Derived(Derived&& rhs) : Base(rhs) // wrong: rhs is an lvalue
{
  // Derived-specific stuff
}

// good
Derived(Derived&& rhs) : Base(std::move(rhs)) // good, calls Base(Base&& rhs)
{
  // Derived-specific stuff
}


There is almost no difference since modern compilers apply RVO
(return value optimization). That means, local x inside f() is
created in place of y.

In some cases, the performance even worst when using std::move()!

David Abrahams has an article on this:
http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/



There are types moveable but not copyable:

std::unique_pointer
std::fstream
std::thread


Reference collapsing:

In pre-C++11 no way to set a reference to a reference: A& & is a compile error
In C++11 we have "reference collapsing" rule:


  A& &   --> A&
  A& &&  --> A&
  A&& &  --> A&
  A&& && --> A&&


template <typename T>
void f(T&&);            // special template argument deduction rule

- If f() called on "lvalue of A"  T --> A&     argument type --> A&
- If f() called on "rvalue of A"  T --> A      argument type --> A



template<typename T, typename Arg>
shared_ptr<T> factory(Arg&& arg)
{
  return shared_ptr<T>(new T(std::forward<Arg>(arg)));
}
template<class S>
S&& forward(typename remove_reference<S>::type& a) noexcept
{
  return static_cast<S&&>(a);
}





Lambda functions
================


#include <algorithm>
#include <iostream>
#include <ostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> v;
    for(int i = 0; i < 10; ++i)
        v.push_back(i);

    for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
    cout << endl;
    return 0;
}



$ g++ l.cpp
$ ./a.out
0 1 2 3 4 5 6 7 8 9
$


[]        lambda-introducer
(int n)   lambda parameter declaration
{ ... }   compound statement



Lambda expressons define classes and construct objects.
The program above is equivalent to:


#include <algorithm>
#include <iostream>
#include <ostream>
#include <vector>

using namespace std;

struct LambdaFunctor
{
    void operator() (int n) const { cout << n << " "; }
};

int main()
{
    vector<int> v;
    for(int i = 0; i < 10; ++i)
        v.push_back(i);

    for_each(v.begin(), v.end(), LambdaFunctor());
    cout << endl;
    return 0;
}



The expression can contain multiply statements


#include <algorithm>
#include <iostream>
#include <ostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> v;
    for(int i = 0; i < 10; ++i)
        v.push_back(i);

    for_each(v.begin(), v.end(), [](int n) {
                    cout << n ;
                    if ( n % 2 )
                        cout << ":odd ";
                    else
                        cout << ":even ";
                                           });
                        cout << endl;
    return 0;
}


0:even 1:odd 2:even 3:odd 4:even 5:odd 6:even 7:odd 8:even 9:odd


If the lambda expession has return value, than the return type
is automatically deduced from that expression:


int main()
{
    vector<int> v;
    for(int i = 0; i < 10; ++i)
        v.push_back(i);

    deque<int> d;

    transform(v.begin(), v.end(), front_inserter(d), [](int n) {return n*n;} );

    for_each(d.begin(), d.end(), [](int n) { cout << n << " "; });

    cout << endl;
    return 0;
}


81 64 49 36 25 16 9 4 1 0



Sometimes it is not easy to deduce the return type. We can explicitly
specify the return type.



#include <algorithm>
#include <iostream>
#include <ostream>
#include <vector>
#include <deque>

using namespace std;

int main()
{
    vector<int> v;
    for(int i = 0; i < 10; ++i)
        v.push_back(i);

    deque<double> d;

    transform(v.begin(), v.end(), front_inserter(d),
                    [](int n) -> double  { return n / 2.0; } );

    for_each(d.begin(), d.end(), [](double n) { cout << n << " "; });

    cout << endl;
    return 0;
}


4.5 4 3.5 3 2.5 2 1.5 1 0.5 0


-> double    is the lambda return type clause
             (it is on the right, because [] should be on left for parsing)



[] means, that the lambda is "stateless", but we can "capture" local variables


#include <algorithm>
#include <iostream>
#include <ostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> v;
    for(int i = 0; i < 10; ++i)
        v.push_back(i);

    int x = 0;
    int y = 0;
    cin >> x >> y;

    v.erase( remove_if(v.begin(),
                       v.end(),
                       [x,y](int n) { return x < n && n < y; }
                      ),
             v.end()
           );

    for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });

    cout << endl;
    return 0;
}


3 6
0 1 2 3 6 7 8 9


We passed the x and y parameters by value. Basically it is equivalent:


struct LambdaFunctor
{
public:
    LambdaFunctor(int a, int b) : m_a(a), m_b(b) { }
    bool operator()(int n) const { return m_a < n && n < m_b; }
private:
    int m_a;
    int m_b;
};

// ...

 v.erase( remove_if(v.begin(),v.end(),LambdaFunctor(x,y)), v.end());


The x and y parameters are copied and being stored in the function object.
We cannot modify the captured values because the operator() in functor is
const.It is a "real" copy, therefore teh modification of x and y is not
reflected inside the lambda.



[=]    capture-default lambda introducer. Captures all locals.


#include <algorithm>
#include <iostream>
#include <ostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> v;
    for(int i = 0; i < 10; ++i)
        v.push_back(i);

    int x = 0;
    int y = 0;
    cin >> x >> y;

    v.erase( remove_if(v.begin(),
                       v.end(),
                       [=](int n) { return x < n && n < y; }
                      ),
             v.end()
           );

    for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });

    cout << endl;
    return 0;
}


3 6
0 1 2 3 6 7 8 9



Lambda expressions are const by default but we can manage to modify x and y.
iNote, that modification of prev does not update local prev variable.


#include <algorithm>
#include <iostream>
#include <ostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> v;
    for(int i = 0; i < 10; ++i)
        v.push_back(i);

    int prev = 0;
    for_each(v.begin(), v.end(), [=](int& r) mutable {
                            const int oldr = r;
                            r *= prev;
                            prev = oldr;
                         });

    for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });

    cout << "prev = " << prev << endl;
    return 0;
}


0 0 2 6 12 20 30 42 56 72 prev = 0


Capture by reference


#include <algorithm>
#include <iostream>
#include <ostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> v;
    for(int i = 0; i < 10; ++i)
        v.push_back(i);

    int prev = 0;
    for_each(v.begin(), v.end(), [&prev](int& r) mutable {
                                    const int oldr = r;
                                    r *= prev;
                                    prev = oldr;
                             });

    for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });

    cout << "prev = " << prev << endl;
    return 0;
}


0 0 2 6 12 20 30 42 56 72 prev = 9


[&]         Capture everything by reference

[=, &x, &y] Capture everything by value but x and y which capured by reference

[&, x, y]   Capture everything by reference but x and y which capured by value




#include <algorithm>
#include <iostream>
#include <ostream>
#include <vector>

using namespace std;

struct X
{
    int s;
    vector<int> v;
    void print() const
    {
        for_each(v.begin(), v.end(), [](int n) { cout << n*s << " "; });
    }
};

int main()
{
    X x;
    x.s = 2;
    for(int i = 0; i < 10; ++i)
        x.v.push_back(i);

    x.print();
    return 0;
}


$ g++ -std=gnu++0x l10.cpp
l10.cpp: In lambda function:
l10.cpp:15:60: error: ‘this’ was not captured for this lambda function



#include <algorithm>
#include <iostream>
#include <ostream>
#include <vector>

using namespace std;

struct X
{
    int s;
    vector<int> v;
    void print() const
    {
        for_each(v.begin(), v.end(), [this](int n) { cout << n*s << " "; });
    }
};

int main()
{
    X x;
    x.s = 2;
    for(int i = 0; i < 10; ++i)
        x.v.push_back(i);

    x.print();
    return 0;
}


- this always captured by value
- you can implicitly capture this with [=]



We can define "nullary" lambdas


#include <algorithm>
#include <iostream>
#include <ostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> v;
    int i = 0;

    generate_n(back_inserter(v), 10, [&] { return i++; } );

    for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });
    return 0;
}


0 1 2 3 4 5 6 7 8 9



Or you can write [&]() { return i++; }

Lambdas can be stored in tr1::functional


#include <algorithm>
#include <functional>
#include <iostream>
#include <ostream>
#include <vector>

using namespace std;
//using namespace std::tr1;

void doit(const vector<int>& v, const function<void (int)>& f)
{
    for_each(v.begin(), v.end(), f);
    cout << endl;
}

int main()
{
    vector<int> v;
    int i = 0;

    generate_n(back_inserter(v), 10, [&] { return i++; } );

    doit(v, [](int n) { cout << n << " "; });

    const function<void (int)>& ff = [](int n) { cout << n << " "; };
    doit(v, ff);

    return 0;
}


0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9


/* const */ int i = some_default_value;

if(someConditionIstrue)
{
    // Do some operations and calculate the value of i; 
    i = // some calculated value; 
}
int x = i; // use i

// But unfortunately in this case there is no way to guarantee it. 
// so now if some one comes and does

i = 10; // This is valid





const int i = [&]{

    int i = some_default_value;

    if(someConditionIstrue)
    {
        // Do some operations and calculate the value of i; 
        i = // some calculated value; 
    }
    return i;

} (); // note: () invokes the lambda!



Generic lambdas in C++14:


auto L = [](const auto& x, auto& y){ return x + y; };

means:

struct /* anonymous */
{
    template <typename T, typename U>
    auto operator()(const T& x, U& y) const // N3386 Return type deduction
    {
        return x + y;
    }
} L;




Smart pointers in C++11
=======================





std::auto_ptr   depricated in C++11
=============


#include <memory>

template< class T > class auto_ptr;
template<> class auto_ptr<void>   // no member functions


auto_ptr hould not be used in new code. Use unique_ptr instead.




std::unique_ptr   since C++11
===============


#include <memory>

template< class T, class Deleter = std::default_delete<T>> class unique_ptr;
template <class T, class Deleter> class unique_ptr<T[],Deleter>;



Moveable (MoveConstructible and MoveAssignable) but not copyable or assignable:



void f()
{
    std::unique_ptr<Foo> up(new Foo());  // up is the only owner
    std::unique_ptr<Foo> up2(up);    // syntax error: can't copy unique_ptr

    std::unique_ptr<Foo> up3;        // nullptr: not owner

    up3 = up;                   // syntax error: can't assign unique_ptr
    up3 = std::move(up);        // ownership moved to up3  

} // up3 destroyed: Foo object is destructed
  // up  destroyed: nop



Convertable to boolean:


void f()
{
    std::unique_ptr<Foo> up(new Foo());  // up is the only owner

    if ( up )  // owner or not
    {
        *up;   // use the object
    }
}




Source/sink:


void sink(std::unique_ptr<Foo> p)
{
    // destroyes Foo object
}

std::unique_ptr<Foo> source()
{
    // creates Foo object and moves back
    return std::unique_ptr<Foo>(new Foo);
}

void f()
{
    auto up = source();

    // use up

    sink(up);                    // syntax error: can't copy
    sink(move(up));              // ok: move

    return 0;
}



Will this work?:


unique_ptr<Foo> source()
{
    std::unique_ptr<Foo> up(new Foo);  // creates a Foo object

    return up;  // ????
}



How to emulate boost:scoped_ptr?:


void f()
{
    boost::scoped_ptr<Foo> sp(new Foo);
    std::unique_ptr<Foo>   up(new Foo);

    boost::scoped_ptr<Foo> sp2;
    std::unique_ptr<Foo>   up2;

    sp2 = sp;  // syntax error
    up2 = up;  // syntax error

    sp2 = std::move(sp);  // syntax error
    up2 = std::move(up);  // ok
}



void f()
{
    const std::unique_ptr<Foo> up(new Foo);

    std::unique_ptr<Foo>   up2;

    up2 = std::move(up);  // syntax error
}



The ugly swap:


void f()
{
    boost::scoped_ptr<Foo> sp1(new Foo);
    const std::unique_ptr<Foo> up1(new Foo);

    {
        boost::scoped_ptr<Foo> sp2(new Foo);
        const std::unique_ptr<Foo> up2(new Foo);

        swap(sp1,sp2);  // ok: swap works on scoped_ptr
        swap(up1,up2);  // syntax error: no move on const 
    }
}




Prefer unique_ptr over shared_ptr until you need more owner

 - replace auto_ptr when want to use a single ownership pointer
 - exception safety for dynamically allocated objects
 - using source/sink strategy for controlling object lifetime
 - use in standard containers when polymorphic usage is needed
 - it is cheap - only the pointer size


Not to use when:

 - need downcast (dynamic cast): No special cast operations are provided




std::shared::ptr    since C++11
================


#include <memory>

template< class T > class shared_ptr;




Shared ownership with copy semantics (copy constructible and copy assignable)



What about unique_array<> and shared_array<>


There is a specialization for unique_ptr<T[]>.

// from http://stackoverflow.com/questions/8624146/c11-standard-scoped-array-wrappers
#include <iostream>
#include <memory>

struct test
{
  ~test() { std::cout << "test::dtor" << std::endl; }
};

int main()
{
  std::unique_ptr<test[]> array(new test[3]);
}

When you run it, you will get this messages.

test::dtor
test::dtor
test::dtor


If you want to use shared_ptr, you should use std::default_delete<T[]>
for deleter since it doesn't have one like shared_ptr<t[]>.

std::shared_ptr<test> array(new test[3], std::default_delete<test[]>());



template<class T> class shared_ptr
{
public:
  typedef T element_type;

  shared_ptr(); // never throws
  template<class Y> explicit shared_ptr(Y * p);
  template<class Y, class D> shared_ptr(Y * p, D d);
  ~shared_ptr(); // never throws

  shared_ptr(shared_ptr const & r); // never throws
  template<class Y> shared_ptr(shared_ptr<Y> const & r); // never throws
  template<class Y> explicit shared_ptr(weak_ptr<Y> const & r);
  template<class Y> explicit shared_ptr(std::auto_ptr<Y> & r);

  shared_ptr & operator=(shared_ptr const & r); // never throws  
  template<class Y> shared_ptr & operator=(shared_ptr<Y> const & r); // never throws
  template<class Y> shared_ptr & operator=(std::auto_ptr<Y> & r);
  void reset(); // never throws
  template<class Y> void reset(Y * p);
  template<class Y, class D> void reset(Y * p, D d);

  T & operator*() const; // never throws
  T * operator->() const; // never throws
  T * get() const; // never throws

  bool unique() const; // never throws
  long use_count() const; // never throws
  operator unspecified-bool-type() const; // never throws
  void swap(shared_ptr & b); // never throws
  template< class Y > bool owner_before( const shared_ptr<Y>& other) const;
  template< class Y > bool owner_before( const std::weak_ptr<Y>& other) const;
};




template<class T, class U>
  bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
template<class T, class U>
  bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
template<class T, class U>
  bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b); // never throws
// .. other comparisons

template<class T> void swap(shared_ptr<T> & a, shared_ptr<T> & b); // never throws

template<class T, class U>
  shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r); // never throws
template<class T, class U>
  shared_ptr<T> const_pointer_cast(shared_ptr<U> const & r); // never throws
template<class T, class U>
  shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r); // never throws
template<class E, class T, class Y>


  std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p);
template<class D, class T>

  D * get_deleter(shared_ptr<T> const & p);

// specializations for atomic_ operations



template< class T, class... Args >
shared_ptr<T> make_shared( Args&&... args );

template< class T, class Alloc, class... Args >
shared_ptr<T> allocate_shared( const Alloc& alloc, Args... args );






template<class T> class weak_ptr
{
public:
  typedef T element_type;

  weak_ptr();
  template<class Y> weak_ptr(shared_ptr<Y> const & r);
  weak_ptr(weak_ptr const & r);
  template<class Y> weak_ptr(weak_ptr<Y> const & r);
  ~weak_ptr();

  weak_ptr & operator=(weak_ptr const & r);
  template<class Y> weak_ptr & operator=(weak_ptr<Y> const & r);
  template<class Y> weak_ptr & operator=(shared_ptr<Y> const & r);

  long use_count() const;
  bool expired() const;     // use_count() == 0
  shared_ptr<T> lock() const;
  // return expired() ? shared_ptr<T>() : shared_ptr<T>(*this)

  void reset();
  void swap(weak_ptr<T> & b);
};

template<class T, class U>
bool operator<(weak_ptr<T> const & a, weak_ptr<U> const & b);
template<class T>
void swap(weak_ptr<T> & a, weak_ptr<T> & b);





Enable_shared_from_this
=======================


class Y: public std::enable_shared_from_this<Y>
{
public:

    std::shared_ptr<Y> f()
    {
        return shared_from_this();
    }
};

int main()
{
    boost::shared_ptr<Y> p(new Y);
    boost::shared_ptr<Y> q = p->f();
    assert(p == q);
    assert(!(p < q || q < p)); // p and q must share ownership
}



#include <iostream>
#include <memory>

int main ()
{
  std::shared_ptr<int> sp1,sp2;
  std::weak_ptr<int> wp;
                                       // sharing group:
                                       // --------------
  sp1 = std::make_shared<int> (20);    // sp1
  wp = sp1;                            // sp1, wp

  sp2 = wp.lock();                     // sp1, wp, sp2
  sp1.reset();                         //      wp, sp2

  sp1 = wp.lock();                     // sp1, wp, sp2

  std::cout << "*sp1: " << *sp1 << '\n';
  std::cout << "*sp2: " << *sp2 << '\n';

  return 0;
}




Implementation
==============



    ----                                   ----------------
   | px | ------------------------------> |     object     |
   | py | -------                          ----------------
    ----         |                                 ^
                 |                                 |
                 |         -----------             |
                 -------->| refCount  |            |
                          | weakCount |            |
                          |     pz    |-------------
                           -----------



Make shared
===========

shared_ptr<std::string> x = make_shared<std::string>("hello, world!");