---------------
template<typename T, size_t N> // tablica N obiektw typu Ts (iso.23.3.2)
struct array {
/*
    typy i operacje jak w wektorze (31.4),
    wyjtek stanowi operacje zmieniajce rozmiar kontenera, konstruktory i assign()
*/
    void fill(const T& v); // przypisuje N kopii v
    void swap(array&) noexcept(noexcept(swap(declval<T&>(), declval<T&>())));

    T __elem[N]; // szczeg implementacyjny
};
---------------
array<int,3> a1 = { 1, 2, 3 }
---------------
void f()
{
    array<string, 4> aa = {"Churchill", "Clare"};
    //
}
---------------
array<int> ax = { 1, 2, 3 }; // bd: nie podano rozmiaru
---------------
array<int,0> a0;
---------------
void f(int n)
{
    array<string,n> aa = {"John's", "Queens' "}; // bd: rozmiar nie jest wyraeniem staym
    //
}
---------------
void f()
{
    array<int,8> aa; // niezainicjowana, na razie
    aa.fill(99);     // przypisanie omiu kopii liczby 99
    //...
}
---------------
void f(int* p, int sz); // interfejs w stylu C

void g()
{
    array<int,10> a;
    f(a,a.size());        // bd: brak konwersji
    f(&a[0],a.size());    // uycie w stylu C
    f(a.data(),a.size()); // uycie w stylu C

    auto p = find(a.begin(),a.end(),777); // uycie w stylu C++/STL
    //...
}
---------------
void h()
{
    Circle a1[10];
    array<Circle,10> a2;
    //...
    Shape* p1 = a1; // OK: tykajca bomba zegarowa
    Shape* p2 = a2; // bd: brak konwersji array<Circle,10> na Shape*
    p1[3].draw();   // katastrofa
}
---------------
tuple_size<array<T,N>>::value     // N
tuple_element<S,array<T,N>>::type // T
---------------
template<size_t index, typename T, size_t N>
    T& get(array<T,N>& a) noexcept;
template<size_t index, typename T, size_t N>
    T&& get(array<T,N>&& a) noexcept;
template<size_t index, typename T, size_t N>
    const T& get(const array<T,N>& a) noexcept;
---------------
array<int,7> a = {1,2,3,5,8,13,25};
auto x1 = get<5>(a);                                 // 13
auto x2 = a[5];                                      // 13
auto sz = tuple_size<decltype(a)>::value;            // 7
typename tuple_element<5,decltype(a)>::type x3 = 13; // x3 jest liczb typu int
---------------
auto sz = tuple_size<decltype(a)>();  // 7

tuple_element<5,decltype(a)> x3 = 13; // x3 jest liczb typu int
---------------
template<size_t N>
class bitset {
public:
    class reference { // referencja do pojedynczego bitu:
        friend class bitset;
        reference() noexcept;
    public:           // obsuguje indeksowanie od zera w przedziale <0,b.size())
        ~reference() noexcept;
        reference& operator=(bool x) noexcept;            // dla b[i] = x;
        reference& operator=(const reference&) noexcept;  // dla b[i] = b[j];
        bool operator~() const noexcept;                  // zwraca ~b[i]
        operator bool() const noexcept;                   // dla x = b[i];
        reference& flip() noexcept;                       // b[i].flip();
    };
    //...
};

---------------
void f()
{
    bitset<10> b1;                                // same 0
    bitset<16> b2 = 0xaaaa;                       // 1010101010101010
    bitset<32> b3 = 0xaaaa;                       // 00000000000000001010101010101010
    bitset<10> b4 {"1010101010"};                 // 1010101010
    bitset<10> b5 {"10110111011110",4};           // 0111011110
    bitset<10> b6 {string{"1010101010"}};         // 1010101010
    bitset<10> b7 {string{"10110111011110"},4};   // 0111011110
    bitset<10> b8 {string{"10110111011110"},2,8}; // 11011101
    bitset<10> b9 {string{"n0g00d"}};             // wyjtek invalid_argument
    bitset<10> b10 = string{"101001"};            // bd: brak jawnej konwersji string na bitset
}

---------------
bitset<9> bs {"110001111"};
cout << bs << '\n';  // zapisuje "110001111" do cout
auto bs2 = bs<<3;    // bs2 == "001111000";
cout << bs2 << '\n'; // zapisuje "001111000" do cout
cin >> bs;           // wczytuje z cin
bs2 = bs>>3;         // bs2 == "000110001", jeli na wejciu byo "110001111"
cout << bs2 << '\n'; // zapisuje "000110001" do cout

---------------
void binary(int i)
{
    bitset<8*sizeof(int)>b=i; // zaoenie, e bajt ma osiem bitw (zobacz rwnie 40.2)

    cout << b.to_string<char,char_traits<char>,allocator<char>>() << '\n'; // oglne i rozwleke
    cout << b.to_string<char>() << '\n'; // uycie domylnych cech i alokatora
    cout << b.to_string<>() << '\n';     // uycie samych wartoci domylnych
    cout << b.to_string() << '\n';       // uycie samych wartoci domylnych
}
---------------
00000000000000000000000001111011
00000000000000000000000001111011
00000000000000000000000001111011
00000000000000000000000001111011
---------------
void binary2(int i)
{
    bitset<8*sizeof(int)>b=i; // zaoenie, e bajt ma osiem bitw (zobacz rwnie 40.2)
    cout << b << '\n';
}
---------------
template<typename A>
class vector<bool,A> { // specjalizacja typu vector<T,A> (31.4)
public:
    using const_reference = bool;
    using value_type = bool;
    // jak vector<T,A>

    class reference {  // obsuga indeksowania od zera w przedziale <0,v.size())
        friend class vector;
        reference() noexcept;
    public:
        ~reference();
        operator bool() const noexcept;
        reference& operator=(const bool x) noexcept;        // v[i] = x
        reference& operator=(const reference& x) noexcept;  // v[i] = v[j]
        void flip() noexcept;                               // zamienia bit na przeciwny: v[i]=~v[i]
    };

    void flip() noexcept; // zamienia na przeciwne wszystkie bity v

    //...
};
---------------
template<typename T, typename U>
struct pair {
    using first_type = T;  // typ pierwszego elementu
    using second_type = U; // typ drugiego elementu

    T first;  // pierwszy element
    U second; // drugi element
    //...
};

---------------
void f()
{
    pair<string,int> p {"Cambridge",1209};
    cout << p.first;  // drukuje "Cambr idge"
    p.second += 800;  // aktualizacja roku
    //...
}
---------------
struct Univ {
    Univ(const string& n, int r) : name{n}, rank{r} { }
    string name;
    int rank;
    string city = "nieznane";
};

using Tup = tuple<string,int>;
Tup t1 {"Columbia",11}; // U.S. News 2012
Tup t2 {"Cambridge",2};

pair<Tup,Tup> p1 {t1,t2};                        // para krotek
pair<Univ,Univ> p2 {piecewise_construct,t1,t2};  // para obiektw typu Univ

---------------
auto p = make_pair("Harvard",1736);
---------------
template<typename ... Types>
class tuple {
public:
    //...
};

---------------
tuple<string,vector<double>,int> t2 = make_tuple("Witajcie, krotki!",vector<int>{1,2,3},'x');
---------------
tuple<int,int,int> rotate(tuple<int,int,int> t)
{
return {t.get<2>(),t.get<0>(),t.get<1>()}; // bd: jawny konstruktor krotki
}

auto t2 = rotate({3,7,9});  // bd: jawny konstruktor krotki
---------------
pair<int,int> rotate(pair<int,int> p)
{
    return {p.second,p.first};
}

auto p2 = rotate({3,7});
---------------
auto t = make_tuple(2.71828,299792458,"Hannibal");
double c;
string name;
tie(c,ignore,name) = t;   // c=299792458; name="Hannibal"
---------------
double c = get<0>(t);     // c=299792458
string name = get<2>(t);  // name="Hannibal"
---------------
tuple<int,double,string> compute();
//...
double c;
string name;
tie(c,ignore,name) = compute(); // wyniki w c i name
---------------
template<typename T, typename D = default_delete<T>>
class unique_ptr {
public:
    using pointer = ptr; // typ zawartego wskanika;
                         // ptr to D::pointer, jeli jest zdefiniowany albo T*
    using element_type = T;
    using deleter_type = D;
    //...
};
---------------
unique_ptr<int[]> make_sequence(int n)
{
    unique_ptr p {new int[n]};
    for (int i=0; i<n; ++i)
        p[i]=i;
    return p;
}
---------------
template<typename T, typename D>
class unique_ptr<T[],D> { // specjalizacja dla tablic (iso.20.7.1.3)
                          // domylny D=default_delete<T> pochodzi z oglnego unique_ptr

public:
// ... jak unique_ptr dla pojedynczych obiektw, ale z [] zamiast * i -> ...
}; 
---------------
class Shape {
    //...
};

class Circle : public Base {
    //...
};

unique_ptr<Shape> ps {new Circle{p,20}};                             // OK
unique_ptr<Shape[]> pa {new Circle[] {Circle{p,20}, Circle{p2,40}};  // bd
---------------
unique_ptr<int> f(unique_ptr<int> p)
{
    ++*p;
    return p;
}

void f2(const unique_ptr<int>& p)
{
    ++*p;
}

void use()
{
    unique_ptr<int> p {new int{7}};
    p=f(p);       // bd: brak konstruktora kopiujcego
    p=f(move(p)); // przekazuje wasno w t i z powrotem
    f2(p);        // przekazuje referencj
}
---------------
extern "C" char* get_data(const char* data); // pobiera dane z fragmentu programu w jzyku C

using PtoCF = void(*)(void*);

void test()
{
    unique_ptr<char,PtoCF> p {get_data("my_data"),free};
    //... uycie *p ...
}   // niejawne free(p)
---------------
template<typename T, typename... Args>
unique_ptr<T> make_unique(Args&&... args)  // domylna wersja z usuwaczem
{
    return unique_ptr<T>{new T{args...}};
}
---------------
struct Node {
vector<Node*> edg es;
    //...
};
---------------
struct Node {
    vector<shared_ptr<Node>> edges;
    thread worker;
    //...
};

---------------
struct S {
    int i;
    string s;
    double d;
    //...
};

auto p = make_shared<S>(1,"Ankh Morpork",4.65);
---------------
template<typename T>
class weak_ptr {
public:
    using element_type = T;
    //...
};

---------------
void owner()
{
    //...
    vector<shared_ptr<Asteroid>> va(100);
    for (int i=0; i<va.size(); ++i) {
        // ... obliczanie ssiadw dla nowej asteroidy...
        va[i].reset(new Asteroid(weak_ptr<Asteroid>(va[neighbor]));
        launch(i);
    }
    //...
}
---------------
void collision(weak_ptr<Asteroid> p)
{
    if (auto q = p.lock()) { // p.lock zwraca wskanik shared_ptr do obiektu p
        //... ta asteroida wci istnieje: oblicza...
    }
    else { // ta asteroida jest ju zniszczona
        p.reset();
    }
}
---------------
p=a.allocate(n);   // zajmuje przestrze dla n obiektw typu T
a.deallocate(p,n); // zwalnia przestrze dla n obiektw typu T wskazywanych przez p
---------------
template<typename T>
struct Simple_alloc { // uywa new[] i delete[] do alokacji i dealokacji bajtw
    using value_type = T;

    Simple_alloc() {}

    T* allocate(size_t n)
        { return reinterpret_cast<T*>(new char[n*sizeof(T)]); }
    void deallocate(T* p, size_t n)
        { delete[] reinterpret_cast<char*>(p); }

    //...
};
---------------
class Arena {
    void* p;
    int s;
public:
    Arena(void* pp, int ss); // alokuje z p[0..ss-1]
};

template<typename T>
struct My_alloc { // uywa obiektu klasy Arena do alokowania i dealokowania bajtw
    Arena& a;
    My_alloc(Arena& aa) : a(aa) { }
    My_alloc() {}
    // typowy kod alokatora
};
---------------
constexpr int sz {100000};
Arena my_arena1{new char[sz],sz};
Arena my_arena2{new char[10*sz],10*sz};

vector<int> v0; // alokuje przy uyciu domylnego alokatora

vector<int,My_alloc<int>> v1 {My_alloc<int>{my_arena1}};  // tworzy w my_arena1

vector<int,My_alloc<int>> v2 {My_alloc<int>{my_arena2}};  // tworzy w my_arena2

vector<int,Simple_alloc<int>> v3;                         // tworzy w pamici wolnej
---------------
template<typename T>
    using Arena_vec = std::vector<T,My_alloc<T>>;
template<typename T>
    using Simple_vec = std::vector<T,Simple_alloc<T>>;

My_alloc<int> Alloc2 {my_arena2};  // nazwany obiekt alokatora

Arena_vec<complex<double>> vcd {{{1,2}, {3,4}}, Alloc2};           // alokator jawny
Simple_vec<string> vs {"Sam Vimes", "Fred Colon", "Nobby Nobbs"};  // domylny alokator
---------------
template<typename T>
class allocator {
public:
    using size_type = size_t;
    using difference_type = ptrdiff_t;
    using pointer = T*;
    using const_pointer = const T*;
    using reference = T&;
    using const_reference = const T&;
    using value_type = T;

    template<typename U>
        struct rebind { using other = allocator<U>; };

    allocator() noexcept;
    allocator(const allocator&) noexcept;
    template<typename U>
        allocator(const allocator<U>&) noexcept;
    ~allocator();

    pointer address(reference x) const noexcept;
    const_pointer address(const_reference x) const noexcept;

    pointer allocate(size_type n, allocator<void>::const_pointer hint = 0); // alokuje n bajtw
    void deallocate(pointer p, size_type n);                                // dealokuje n bajtw

    size_type max_size() const noexcept;

    template<typename U, typename... Args>
        void construct(U* p, Args&&... args);  // new(p) U{args}

    template<typename U>
        void destroy(U*p); // p->~U()
};
---------------
template<typename U>
using other = allocator<U>;
---------------
using Link_alloc = typename A::template rebind<Link>::other;
---------------
template<typename T, typename A = allocator<T>>
class list {
private:
    class Link { /*...*/};

    using Link_alloc = typename A:: template rebind<Link>::other; // allocator<Link>

    Link_alloc a; // alokator cza 
    A alloc;      // alokator listy
    //...
};
---------------
template<>
class allocator<void> {
public:
    typedef void* pointer;
    typedef const void* const_pointer;
    typedef void value_type;
    template<typename U> struct rebind { typedef allocator<U> other; };
};
---------------
template<typename A> // iso.20.6.8
struct allocator_traits {
    using allocator_type = A;
    using value_type = A::value_type;
    using pointer = value_type;                                                  // sztuczka
    using const_pointer = Pointer_traits<pointer>::rebind<const value_type>;     // sztuczka
    using void_pointer = Pointer_traits<pointer>::rebind<void>;                  // sztuczka
    using const_void_pointer = Pointer_traits<pointer>::rebind<const void>;      // sztuczka
    using difference_type = Pointer_traits<pointer>::difference_type;            // sztuczka
    using size_type = Make_unsigned<difference_type>;                            // sztuczka
    using propagate_on_container_copy_assignment = false_type;                   // sztuczka
    using propagate_on_container_move_assignment = false_type;                   // sztuczka
    using propagate_on_container_swap = false_type;                              // sztuczka

    template<typename T> using rebind_alloc = A<T,Args>;                         // sztuczka
    template<typename T> using rebind_traits = Allocator_traits<rebind_alloc<T>>;

    static pointer allocate(A& a, size_type n) { return a.allocate(n); }         // sztuczka
    static pointer allocate(A& a, size_type n, const_void_pointer hint)          // sztuczka
        { return a.allocate(n,hint); }
    static void deallocate(A& a, pointer p, size_type n) { a.deallocate(p, n); } // sztuczka

    template<typename T, typename ... Args>
        static void construct(A& a, T* p, Args&&... args)                        // sztuczka
        { ::new (static_cast<void*>(p)) T(std::forward<Args>(args)...); }
    template<typename T>
        static void destroy(A& a, T* p) { p->T(); }                              // sztuczka

    static size_type max_size(const A& a)                                        // sztuczka
        { return numeric_limits<size_type>::max() }
    static A select_on_container_copy_construction(const A& rhs) { return a; }   // sztuczka
};
---------------
template<typename P>                    // iso.20.6.3
struct pointer_traits {
    using pointer = P;
    using element_type = T;             // sztuczka
    using difference_type = ptrdiff_t;  // sztuczka

    template<typename U>
        using rebind = T*;              // sztuczka

    static pointer pointer_to(a);       // sztuczka
};

template<typename T>
struct pointer_traits<T*>{
    using pointer = T*;
    using element_type = T;
    using difference_type = ptrdiff_t;
    template<typename U>
        using rebind = U*;

    static pointer pointer_to(x) noexcept { return addressof(x); }
};
---------------
template<typename OuterA, typename... InnerA> // iso.20.12.1
class scoped_allocator_adaptor : public OuterA {
private:
    using Tr = allocator_traits<OuterA>;
public:
    using outer_allocator_type = OuterA;
    using inner_allocator_type = see below;
    using value_type = typename Tr::value_type;
    using size_type = typename Tr::size_type;
    using difference_type = typename Tr::difference_type;
    using pointer = typename Tr::pointer;
    using const_pointer = typename Tr::const_pointer;
    using void_pointer = typename Tr::void_pointer;
    using const_void_pointer = typename Tr::const_void_pointer;
    using propagate_on_container_copy_assignment = /* zobacz iso.20.12.2*/;
    using propagate_on_container_move_assignment = /* zobacz iso.20.12.2*/;
    using propagate_on_container_swap = /* zobacz iso.20.12.2*/;
    //...
};
---------------
// wektor i string uywaj wasnych (domylnych) alokatorw:
using svec0 = vector<string>;
svec0 v0;

// wektor (tylko) uywa My_alloc, a string uywa wasnego alokatora (domylnego):
using Svec1 = vector<string,My_alloc<string>>;
Svec1 v1 {My_alloc<string>{my_arena1}};

// vector i string uywaj My_alloc (jak wyej):
using Xstring = basic_string<char,char_traits<char>, My_alloc<char>>;
using Svec2 = vector<Xstring,scoped_allocator_adaptor<My_alloc<Xstring>>>;
Svec2 v2 {scoped_allocator_adaptor<My_alloc<Xstring>>{my_arena1}};

// vector uywa wasnego alokatora (domylnego), a string uywa My_alloc:
using Xstring2 = basic_string<char, char_traits<char>, My_alloc<char>>;
using Svec3 = vector<xstring2,scoped_allocator_adaptor<My_alloc<xstring>,My_alloc<char>>>;
Svec3 v3 {scoped_allocator_adaptor<My_alloc<xstring2>,My_alloc<char>>{my_arena1}};

---------------
int* p = new int[100];
p+=10;
//... tu moe zosta uruchomiony odmiecacz...
p-=10;
*p = 10; // czy mona mie pewno, e ta liczba nadal tu jest?
---------------
int* p = new int;
int x = reinterpret_cast<int>(p); // nawet nie przenone
p = nullptr;
//... tu moe zosta uruchomiony odmiecacz...
p = reinterpret_cast<int*>(x);
*p = 10; // czy mona mie pewno, e ta liczba nadal tu jest?
---------------
int* p = new int;
cout << p;
p = nullptr;
//... tu moe zosta uruchomiony odmiecacz...
cin >> p;
*p = 10; // czy mona mie pewno, e ta liczba nadal tu jest?
---------------
using Link = pair<Value,long>;
long xor(Link* pre , Link* suc)
{
    static_assert(sizeof(Link*)<=sizeof(long),"typ long jest mniejszy od wskanika");
    return long{pre}^long{suc};
}
void insert_between(Value val, Link* pre , Link* suc)
{
    Link*p = new Link{val,xor(pre,suc)};
    pre->second = xor(xor(pre->second,suc),p);
    suc->second = xor(p,xor(suc->second,pre));
}
---------------
void declare_reachable(void*p);   // obiekt wskazywany przez p nie moe zosta usunity przez odmiecacz
template<typename T>
    T* undeclare_reachable(T* p); // cofa declare_reachable()

void declare_no_pointers(char* p, size_t n);   // p[0:n) nie przechowuje wskanikw
void undeclare_no_pointers(char* p, size_t n); // cofa declare_no_pointers()
---------------
enum class pointer_safety {relaxed, preferred, strict };

pointer_safety get_pointer_safety();
---------------
template<typename T>
    pair<T*,ptrdiff_t> get_temporary_buffer(ptrdiff_t); // alokuje, nie inicjuje
template<typename T>
    void return_temporary_buffer(T*);                   // dealokuje, nie niszczy
---------------
template<typename Out, typename T>
class raw_storage_iterator : public iterator<output_iterator_tag,void,void,void,void> {
    Out p;
public:
    explicit raw_storage_iterator(Out pp) : p{pp} { }
    raw_storage_iterator& operator*() { return *this; }

    raw_storage_iterator& operator=(const T& val)
    {
        new(&*p) T{val};  // wstawia val do *p (11.2.4)
        return *this;
    }

    raw_storage_iterator& operator++() {++p; return *this; } // preinkrementacja
    raw_storage_iterator operator++(int)                     // postinkrementacja
    {
        auto t =*this;
        ++p;
        return t;
    }
};
---------------
void test1()
{
    auto pp = get_temporary_buffer<string>(1000); // zajcie niezainicjowanej przestrzeni
    if (pp.second<1000) {
        //... obsuga niepowodzenia alokacji...
    }
    auto p = raw_storage_iterator<string*,string>(pp.first); // iterator
    generate_n(p,a.size(),
         [&]{ next_permutation(seed,seed+sizeof(seed)-1); return seed; });
    //...
    return_temporary_buffer(p);
}