---------------
[]    ()    ->    ++    --    new    delete
---------------
struct Assoc {
    vector<pair<string,int>> vec; // wektor par {nazwa,warto}

    const int& operator[] (const string&) const;
    int& operator[](const string&);
};
---------------
int& Assoc::operator[](const string& s)
    // szuka s; zwraca referencj do wartoci, jeli j znajdzie;
    // w przeciwnym przypadku tworzy now par {s,0} i zwraca referencj do jej wartoci
{
    for (auto x : vec)
        if (s == x.first) return x.second;

    vec.push_back({s,0});      // warto pocztkowa: 0

    return vec.back().second;  // zwraca ostatni element (31.2.2)
}
---------------
int main() // liczy wystpienia kadego sowa na wejciu
{
    Assoc values;
    string buf;
    while (cin>>buf) ++values[buf];
    for (auto x : values.vec)
    cout << '{' << x.first << ',' << x.second << "}\n";
}
---------------
struct Action {
    int operator()(int);
    pair<int,int> operator()(int,int);
    double operator()(double);
    //...
};

void f(Action act)
{
    int x = act(2);
    auto y = act(3,4);
    double z = act(2.3);
    //...
};
---------------
class Add {
    complex val;
public:
    Add(complex c) :val{c} { }                      // zapisuje warto
    Add(double r, double i) :val{{r,i}} { }
    void operator()(complex& c) const { c += val; } // dodaje warto do swojego argumentu
};
---------------
void h(vector<complex>& vec, list<complex>& lst, complex z)
{
    for_each(vec.begin(),vec.end(),Add{2,3});
    for_each(lst.begin(),lst.end(),Add{z});
}
---------------
template<typename Iter, typename Fct>
Fct for_each(Iter b, Iter e, Fct f)
{
    while (b != e) f(*b++);
    return f;
}
---------------
void h2(vector<complex>& vec, list<complex>& lst, complex z)
{
    for_each(vec.begin(),vec.end(),[](complex& a){ a+={2,3}; });
    for_each(lst.begin(),lst.end(),[](complex& a){ a+=z; });
}
---------------
class Ptr {
    //...
    X* operator->();
};
---------------
void f(Ptr p)
{
    p->m = 7; // (p.operator->())->m = 7
}
---------------
void g(Ptr p)
{
    X* q1 = p->;            // bd skadni
    X* q2 = p.operator->(); // OK
}
---------------
template<typename T>
class Disk_ptr {
    string identifier;
    T* in_core_address;
    //...
public:
    Disk_ptr(const string& s) : identifier{s}, in_core_address{nullptr} { }
    ~Disk_ptr() { write_to_disk(in_core_address,identifier); }

    T* operator->()
    {
        if (in_core_address == nullptr)
            in_core_address = read_from_disk(identifier);
        return in_core_address;
    }
};
---------------
struct Rec {
    string name;
    //...
};

void update(const string& s)
{
    Disk_ptr<Rec> p {s}; // tworzy obiekt typu Disk_ptr dla s

    p->name = "Roscoe";  // zmienia s; w razie potrzeby najpierw pobiera go z dysku
    //...
}                        // destruktor p zapisuje obiekt z powrotem na dysku
---------------
p->m == (*p).m   // true
(*p).m == p[0].m // true
p->m == p[0].m   // true
---------------
template<typename T>
class Ptr {
    Y* p;
public:
    Y* operator->() { return p; }         // dereferencja w celu uzyskania dostpu do skadowej
    Y& operator*() { return*p; }          // dereferencja w celu uzyskania dostpu do caego obiektu
    Y& operator[](int i) { return p[i]; } // dereferencja w celu uzyskania dostpu do elementu
     //...
};
---------------
void f1(X a) // tradycyjny sposb uycia
{
    X v[200];
    X* p = &v[0];
    p--;
    *p=a; // ups: p jest poza zakresem, a bd nie zostanie przechwycony
    ++p;
    *p=a; // OK
}
---------------
void f2(Ptr<X> a) // kontrolowane
{
    X v[200];
    Ptr<X> p(&v[0],v);
    p--;
    *p=a; // bd wykonawczy: p jest poza zakresem
    ++p;
    *p=a; // OK
}
---------------
template<typename T>
class Ptr {
    T* ptr;
    T* array;
    int sz;
public:
    template<int N>
        Ptr(T* p, T(&a)[N]); // wie si z tablic a, sz==N, warto pocztkowa p
    Ptr(T* p, T* a, int s);  // wie si z tablic a o rozmiarze s, warto pocztkowa p
    Ptr(T* p);               // wie si z pojedynczym obiektem, sz==0, warto pocztkowa p

    Ptr& operator++();       // przedrostek
    Ptr& operator--();       // przedrostek
    Ptr operator++(int);     // przyrostek
    Ptr operator--(int);     // przyrostek

    T& operator*();          // przedrostek
};
---------------
template<typename T>
Ptr& Ptr<T>::operator++() // zwiksza biecy obiekt i zwraca wynik tego zwikszenia
{
    // ... sprawdzenie, czy mona wskazywa obiekt ptr+1...
    ++ptr;
    return *this;
}

template<typename T>
Ptr Ptr<T>::operator++(int) // zwiksza i zwraca Ptr o starej wartoci
{
    // ... sprawdzenie, czy mona wskazywa ptr+1...
    Ptr<T> old {ptr,array,sz};
    ++ptr;
    return old;
}
---------------
void f3(T a) // kontrolowane
{
    T v[200];
    Ptr<T> p(&v[0],v);
    p.operator--(0);   // przyrostek: p--
    p.operator*() = a; // bd wykonawczy: p jest poza zakresem
    p.operator++();    // przedrostek: ++p
    p.operator*() = a; // OK
}
---------------
void* operator new(size_t);            // zastosowanie dla pojedynczego obiektu
void* operator new[](size_t);          // zastosowanie dla tablicy
void operator delete(void*, size_t);   // zastosowanie dla pojedynczego obiektu
void operator delete[](void*, size_t); // zastosowanie dla tablicy

// wicej wersji znajduje si w sekcji 11.2.4
---------------
class Employee {
public:
    //...

    void* operator new(size_t);
    void operator delete(void*, size_t);
    void* operator new[](size_t);
    void operator delete[](void*, size_t);
};
---------------
void* Employee::operator new(size_t s)
{
    // alokuje s bajtw pamici i zwraca wskanik do niej
}

void Employee::operator delete(void* p, size_t s)
{
    if (p) { // usuwa tylko, jeli p!=0; zobacz 11.2, 11.2.3
             // zakada, e p wskazuje s bajtw pamici alokowanych przez funkcj Employee::operator new()
             // i zwalnia j, aby bya dostpna do uytku w innym celu
    }
}
---------------
Employee*p = new Manager;  // potencjalny kopot (dokadny typ zostaje utracony)
//...
delete p;                  // miejmy nadziej, e klasa Employee zawiera destruktor wirtualny
---------------
123  // int
1.2  // double
1.2F // float
'a'  // char
1ULL // long long bez znaku
0xD0 // szesnastkowy bez znaku
"as" // acuch w stylu C (const char[3])
---------------
"Cze!"s        // string, nie "tablica znakw zakoczona zerem"
1.2i             // cz urojona
101010111000101b // liczba binarna
123s             // sekundy
123.56km         // nie mile! (jednostki)
1234567890123456789012345678901234567890x // zwikszona precyzja
---------------
constexpr complex<double> operator"" i(long double d) // litera czci urojonej
{
    return {0,d}; // complex jest typem literaowym
}
std::string operator"" s(const char* p, size_t n) // litera typu std::string
{
    return string{p,n}; // wymaga alokacji w pamici wolnej
}
---------------
template<typename T> void f(const T&);

void g()
{
    f("Witaj");    // przekazanie wskanika do char*
    f("Witaj"s);   // przekazanie picioznakowego obiektu typu string
    f("Witaj\n"s); // przekazanie szecioznakowego obiektu typu string

    auto z = 2+1i; // complex{2,1}
}
---------------
Bignum operator"" x(const char* p)
{
    return Bignum(p);
}

void f(Bignum);

f(123456789012345678901234567890123456789012345x);
---------------
string operator"" s(const char* p, size_t n);

string s12 = "jeden dwa"s;    // wywouje operator ""s("jeden dwa",7)
string s22 = "dwa\ndwa"s;     // wywouje operator ""s("dwa\ndwa",7)
string sxx = R"(dwa\ndwa)"s;  // wywouje operator ""s("dwa\\ndwa",8)
---------------
string operator"" SS(const char* p); // ostrzeenie: to nie dziaa zgodnie z oczekiwaniami
string s12 = "jeden dwa"SS;          // bd: brak odpowiedniego operatora literaowego

string s13 = 13SS;                   // OK, ale po co kto miaby to robi?
---------------
template<char...>
constexpr int operator"" _b3(); // o podstawie 3
---------------
201_b3 // znaczy operator"" b3<'2','0','1'>(); a wic 2*9+0*3+1 == 19
241_b3 // znaczy operator"" b3<'2','4','1'>(); a wic bd: 4 nie jest cyfr trjkow
---------------
constexpr int ipow(int x, int n) // x do potgi n
{
    return n>0?x*ipow(x,n-1):1;
}

template<char...> struct helper; // nieuywany oglny szablon (szablon pierwotny - 25.3.1.1)

template<char c>
struct helper<c> { // obsuga jednej cyfry
    static_assert('0'<=c&&c<'3',"Nietrjkowa cyfra");
    static constexpr int value() { return c-'0'; }
};

template<char c, char... tail>
struct helper<c, tail...> { // obsuga kilku cyfr
    static_assert('0'<=c&&c<'3',"Nietrjkowa cyfra");
    static constexpr int value() { return (c-'0')*ipow(3,sizeof...(tail)) + helper<tail...>::value(); }
};
---------------
template<char... chars>
constexpr int operator"" _b3()
{
    return helper<chars...>::value();
}
---------------
namespace Numerics {
    //...

    class Bignum { /*...*/};

    namespace literals {
        Bignum operator"" x(char const*);
    }
    //...
}

using namespace Numerics::literals;
---------------
123km  // zarezerwowane dla biblioteki standardowej
123_km // dostpne do uytku dla programistw
---------------
class String {
public:
    String();                         // konstruktor domylny: x{""}

    explicit String(const char* p);   // konstruktor dla acucha w stylu: x{"Euler"}

    String(const String&);            // konstruktor kopiujcy
    String& operator=(const String&); // przypisanie kopiujce
    String(String&& x);               // konstruktor przenoszcy
    String& operator=(String&& x);    // przypisanie przenoszce

    ~String() { if (short_max<sz) delete[] ptr; } // destruktor
    //...
};
---------------
class String {
public:
    //...

    char& operator[](int n) { return ptr[n]; }   // niekontrolowany dostp do elementw
    char operator[](int n) const { return ptr[n]; }

    char& at(int n) { check(n); return ptr[n]; } // dostp do elementw z kontrol zakresu
    char at(int n) const { check(n); return ptr[n]; }

    String& operator+=(char c);     // dodaje c na kocu

    char* c_str() { return ptr; }   // dostp do acucha w stylu C
    const char* c_str() const { return ptr; }

    int size() const { return sz; } // liczba elementw
    int capacity() const            // elementy plus dostpna przestrze
        { return (sz<=short_max) ? short_max : sz+space; }
    //...
};
---------------
int hash(const String& s)
{
    if (s.size()==0) return 0;
    int h {s[0]};     // niekontrolowany dostp do s
    for (int i {1}; i<s.size(); ++i)
        h ^= s[i]>>1; // niekontrolowany dostp do s
    return h;
}
---------------
void print_in_order(const String& s,const vector<int>& index)
{
    for (auto x : index)
        cout << s.at(x) << '\n'; // kontrolowany dostp do s
}
---------------
class String {
/*
    Prosty typ acuchowy zoptymalizowany dla krtkich acuchw

    size()==sz okrela liczb elementw
    Jeli size()<= short_max, znaki s przechowywane w samym obiekcie;
    w przeciwnym przypadku uywana jest pami wolna.

    ptr wskazuje pocztek sekwencji znakw
    Sekwencja ta jest zakoczona zerem: ptr[size()]==0;
    Dziki temu mona uywa funkcji z biblioteki C oraz atwo zwraca acuchy w stylu C: c_str()
    Aby dodawanie znakw na kocu acucha byo wydajne, klasa String zwiksza si poprzez podwojenie obszaru alokacji;
    Funkcja capacity() okrela ilo przestrzeni dostpnej dla znakw (nie liczc kocowego 0): sz+space
*/
public:
    //...
private:
    static const int short_max = 15;
    int sz;                   // liczba znakw
    char* ptr;
    union {
        int space;            // nieuywana alokowana przestrze
        char ch[short_max+1]; // pozostawienie miejsca dla kocowego 0
    };

    void check(int n) const   // sprawdzanie zakresu
    {
        if (n<0 || sz<=n)
            throw std::out_of_range("String::at()");
    }

    // pomocnicze funkcje skadowe:
    void copy_from(const String& x);
    void move_from(String& x);
};
---------------
char* expand(const char* ptr, int n) // rozszerzenie w pamici wolnej
{
    char* p = new char[n];
    strcpy(p,ptr); // 43.4
    return p;
}
---------------
void String::copy_from(const String& x)
    // czyni *this kopi x
{
    if (x.sz<=short_max) {         // kopiuje *this
        memcpy(this,&x,sizeof(x)); // 43.5
        ptr = ch;
    }
    else {                         // kopiuje elementy
        ptr = expand(x.ptr,x.sz+1);
        sz = x.sz;
        space = 0;
    }
}
---------------
void String::move_from(String& x)
{
    if (x.sz<=short_max) {         // kopiuje *this
        memcpy(this,&x,sizeof(x)); // 43.5
        ptr = ch;
    }
    else {                         // bierze elementy
        ptr = x.ptr;
        sz = x.sz;
        space = x.space;
        x.ptr = x.ch;              // x=""
        x.sz = 0;
        x.ch[0]=0;
    }
}
---------------
String::String()      // konstruktor domylny: x{""}
    : sz{0}, ptr{ch}  // ptr wskazuje elementy, ch jest pocztkow lokalizacj (19.3.3)
{
    ch[0] = 0;        // kocowe 0
}
---------------
String::String(const char* p)
    :sz{strlen(p)},
    ptr{(sz<=shor t_max) ? ch : new char[sz+1]},
    space{0}
{
    strcpy(ptr,p); // kopiuje znaki do ptr z p
}
---------------
String::String(const String& x) // konstruktor kopiujcy
{
    copy_from(x);               // kopiuje reprezentacj z x
}
---------------
String::String(String&& x) // konstruktor przenoszcy
{
    move_from(x);
}
---------------
String& String::operator=(const String& x)
{
    if (this==&x) return *this; // rozwizuje problem z samoprzypisaniem
    char* p = (short_max<sz) ? ptr : 0;
    copy_from(x);
    delete[] p;
    return *this;
}
---------------
String& String::operator=(String&& x)
{
    if (this==&x) return *this;     // rozwizuje problem z samoprzypisaniem (x = move(x) to szalestwo)
    if (short_max<sz) delete[] ptr; // usuwa cel
    move_from(x);                   // nie zgasza wyjtkw
    return *this;
}
---------------
String& String::operator+=(char c)
{
    if (sz==short_max) {     // rozszerza do dugiego acucha
        int n = sz+sz+2;     // podwaja alokacj (+2 dotyczy kocowego 0)
        ptr = expand(ptr,n);
        space = n-sz-2;
    }
    else if (short_max<sz) {
        if (space==0) {      // rozszerza w pamici wolnej
            int n = sz+sz+2; // podwaja alokacj (+2 dotyczy kocowego 0)
            char* p = expand(ptr,n);
            delete[] ptr;
            ptr = p;
            space = n-sz-2;
        }
        else
            --space;
        }
    ptr[sz] = c;   // dodaje c na kocu
    ptr[++sz] = 0; // zwiksza rozmiar i ustawia znak kocowy

    return *this;
}
---------------
ostream& operator<<(ostream& os, const String& s)
{
    return os << s.c_str(); // 36.3.3
}

istream& operator>>(istream& is, String& s)
{
    s = ""; // kasuje docelowy acuch
    is>>ws; // pomija biae znaki (38.4.1.1, 38.4.5.2)
    char ch='';
    while(is.get(ch) && !isspace(ch))
    s+=ch;
    return is;
}
---------------
bool operator==(const String& a, const String& b)
{
    if (a.size()!=b.size())
        return false;
    for (int i = 0; i!=a.size(); ++i)
        if (a[i]!=b[i])
            return false;
    return true;
}

bool operator!=(const String& a, const String& b)
{
    return !(a==b);
}
---------------
char* begin(String& x) // dostp do acuchw w stylu C
{
    return x.c_str();
}

char* end(String& x)
{
    return x.c_str()+x.size();
}
const char* begin(const String& x)
{
    return x.c_str();
}

const char* end(const String& x)
{
    return x.c_str()+x.size();
}
---------------
String& operator+=(String& a, const String& b)     // konkatenacja
{
    for (auto x : b)
        a+=x;
    return a;
}
String operator+(const String& a, const String& b) // konkatenacja
{
    String res {a};
    res += b;
    return res;
}
---------------
String s = "Njal ";
s += "Gunnar"; // konkatenacja: dodaje acuch na kocu s
---------------
String operator"" _s(const char* p, size_t)
{
    return String{p};
}
---------------
void f(const char*);   // acuch w stylu C
void f(const String&); // nasz acuch

void g()
{
    f("Madden's");        // f(const char*)
    f("Christopher's"_s); // f(const String&);
}
---------------
int main()
{
    String s ("abcdefghij");
    cout << s << '\n';
    s += 'k';
    s += 'l';
    s += 'm';
    s += 'n';
    cout << s << '\n';
    String s2 = "Bez";
    s2 += " pracy nie ma koaczy";
    cout << s2 << '\n';

    String s3 = "qwerty";
    s3 = s3;
    String s4 ="Pjde, ki t chmurno w gb flaszy!";
    s4 = s4;
    cout << s3 << " " << s4 << "\n";
    cout << s + ". " + s3 + String(". ") + "Koskie pira\n";

    String buf;
    while (cin>>buf && buf!="quit")
    cout << buf << " " << buf.size() << " " << buf.capacity() << '\n';
}
---------------
constexpr int rc_max {4}; // rozmiar wiersza i kolumny

class Matrix;

class Vector {
    float v[rc_max];
    //...
    friend Vector operator*(const Matrix&, const Vector&);
};

class Matrix {
    Vector v[rc_max];
    // ...
    friend Vector operator*(const Matrix&, const Vector&);
};
---------------
Vector operator*(const Matrix& m, const Vector& v)
{
    Vector r;
    for (int i = 0; i!=rc_max; ++i) { // r[i] = m[i] * v;
        r.v[i] = 0;
        for (int j = 0; j!=rc_max; ++j)
            r.v[i] += m.v[i].v[j] * v.v[j];
    }
    return r;
}
---------------
class List_iterator {
    //...
    int* next();
};

class List {
    friend int* List_iterator::next();
    //...
};
---------------
class List {
    friend class List_iterator;
    //...
};
---------------
template<typename T>
    class X {
    friend T;
    friend class T; // sowo class nie jest potrzebne
    //...
};
---------------
class C1 { }; // bdzie zaprzyjaniona z klas N::C
void f1();    // bdzie zaprzyjaniona z klas N::C

namespace N {
    class C2 { }; // bdzie zaprzyjaniona z klas C
    void f2() { } // bdzie zaprzyjaniona z klas C

    class C {
        int x;
    public:
        friend class C1; // OK (wczeniej zdefiniowana)
        friend void f1();
        friend class C2; // OK (wczeniej zdefiniowana)
        friend void f2();
        friend class C3; // OK (zdefiniowana w otaczajcej przestrzeni nazw)
        friend void f3();
        friend class C4; // po raz pierwszy zadeklarowana w N i przyjmuje si, e jest w N
        friend void f4();
    };

    class C3 {};                // zaprzyjaniona z C
    void f3() { C x; x.x = 1; } // OK: zaprzyjaniona z C
} // przestrze nazw N

class C4 { };                   // niezaprzyjaniona z N::C
void f4() { N::C x; x.x = 1; }  // bd: x jest prywatna a f4() nie jest zaprzyjaniona z klas N::C
---------------
void f(Matrix& m)
{
    invert(m); // funkcja zaprzyjaniona invert() klasy Matrix
}
---------------
// brak funkcji f() w tym zakresie

class X {
    friend void f();         // bezuyteczna
    friend void h(const X&); // moe zosta znaleziona poprzez swj argument
};

void g(const X& x)
{
    f();  // brak funkcji f() w zakresie
    h(x); // funkcja zaprzyjaniona klasy X
}
---------------
class X {
    //...
    X(int);

    int m1();          // skadowa
    int m2() const;

    friend int f1(X&); // zaprzyjaniona, nieskadowa
    friend int f2(const X&);
    friend int f3(X);
};
---------------
void g()
{
    99.m1(); // bd: nie bdzie prby wykonania operacji X(99).m1()
    99.m2(); // bd: nie bdzie prby wykonania operacji: X(99).m2()
}
---------------
void h()
{
    f1(99); // bd: nie bdzie prby wykonania operacji f1(X(99)): niestay argument X&
    f2(99); // OK: f2(X(99)); argument const X&
    f3(99); // OK: f3(X(99)); argument X
}