---------------
while (b!=e) { // uywa!=, nie za <
    // jakie dziaania
    ++b; // przejcie do nastpnego elementu
}
---------------
auto p = find(v.begin(),v.end(),x);  // szuka x w v

if (p!=v.end()) {
    // x znaleziono na pozycji p
}
else {
    // nie znaleziono x w <v.begin(),v.end())
}
---------------
template<typename Iter>
void forward(Iter p, int n)
{
    while (n>0)
        *p++ = --n;
}

void user()
{
    vector<int> v(10);
    forward(v.begin(),v.size()); // OK
    forward(v.begin(),1000);     // powane problemy
}

---------------
template<typename Iter>
void advance_helper(Iter p, int n, random_access_iterator_tag)
{
    p+=n;
}
---------------
template<typename Iter>
void advance_helper(Iter p, int n, bidirectional_iterator_tag)
{
    if (0<n)
        while (n--) ++p;
    else if (n<0)
        while (n++) --p;
}
---------------
template<typename Iter>
void advance(Iter p, int n) // uyje optymalnego algorytmu
{
    advance_helper(p,n,typename iterator_traits<Iter>::iterator_category{});
}
---------------
template<typename Iter>
struct iterator_traits {
    using value_type = typename Iter::value_type;
    using difference_type = typename Iter::difference_type;
    using pointer = typename Iter::pointer;                     // typ wskanikowy
    using reference = typename Iter::reference;                 // typ referencyjny
    using iterator_category = typename Iter::iterator_category; // (tag)
};
---------------
template<typename T>
struct iterator_traits<T*>{ // specjalizacja dla wskanikw
    using difference_type = ptrdiff_t;
    using value_type = T;
    using pointer = T*;
    using reference = T&;
    using iterator_category = random_access_iterator_tag;
};
---------------
template<typename Iter>
typename Iter::value_type read(Iter p, int n) // nieoglne
{
    //... sprawdzanie...
    return p[n];
}
---------------
template<typename Iter>
typename iterator_traits<Iter>::value_type read(Iter p, int n) // bardziej oglne
{
    //... sprawdzanie...
    return p[n];
}
---------------
template<typename Iter>
using Category<Iter> = typename std::iterator_traits<Iter>::iterator_category;

template<typename Iter>
using Difference_type<Iter> = typename std::iterator_traits<Iter>::difference_type;
---------------
tempate<typename Iter>
void f(Iter p, Iter q)
{
    Iter::difference_type d1 = distance(p,q);          // bd skadni: brak typename

    typename Iter::difference_type d2 = distance(p,q); // nie dziaa dla wskanikw itd.
    typename iterator_traits<Iter>::difference_type d3 = distance(p,q); // OK, ale brzydkie
    Difference_type<Iter> d4 = distance(p,q);                           // OK, znacznie lepsze

    auto d5 = distance(p,q); // OK, jeli nie trzeba podawa typu bezporednio
    //...
}
---------------
template<typename Cat, typename T, typename Dist = ptrdiff_t, typename Ptr = T*, typename Ref = T&>
struct iterator {
    using value_type = T;
    using difference_type = Dist ;  // typ uywany przez distance()
    using pointer = Ptr;            // typ wskanikowy
    using reference = Ref;          // typ referencyjny
    using iterator_category = Cat;  // kategoria (tag)
};
---------------
template<typename Iter>
class reverse_iterator
    : public iterator<Iterator_category<Iter>,
                      Value_type<Iter>,
                      Difference_type<Iter>,
                      Pointer<Iter>,
                      Reference<Iter>> {
public:
    using iterator_type = Iter;

    reverse_iterator(): current{} { }
    explicit reverse_iterator(Iter p): current{p} { }
    template<typename Iter2>
        reverse_iterator(const reverse_iterator<Iter2>& p) :current(p.base()) { }

    Iter base() const { return current; } // bieca warto iteratora

    reference operator*() const { tmp = current; return*--tmp; }
    pointer operator->() const;
    reference operator[](difference_type n) const;

    reverse_iterator& operator++() { --current; return *this; } // uwaga: nie ++
    reverse_iterator operator++(int) { reverse_iterator t = current; --current; return t; }
    reverse_iterator& operator--() { ++current; return *this; } // uwaga: nie --
    reverse_iterator operator--(int) { reverse_iterator t = current; ++current; return t; }

    reverse_iterator operator+(difference_type n) const;
    reverse_iterator& operator+=(difference_type n);
    reverse_iterator operator-(difference_type n) const;
    reverse_iterator& operator-=(difference_type n);
    //...
protected:
    Iterator current; // current wskazuje element za wskazywanym przez *this
private:
    //...
    iterator tmp;     // dla obiektw tymczasowych, ktre musz istnie poza zakresem funkcji
};
---------------
void f(vector<int>& v, list<char>& lst)
{
    v.rbegin()[3] = 7;             // OK: iterator swobodny
    lst.rbegin()[3] = '4';         // bd: operator dwukierunkowy nie obsuguje []
    *(next(lst.rbegin(),3)) = '4'; // OK!
}
---------------
auto ri = find(v.rbegin(),v.rend(),val);  // ostatnie wystpienie
---------------
template<typename C, typename Val>
auto find_last(C& c, Val v) -> decltype(c.begin()) // uycie iteratora C w interfejsie
{
    auto ri = find(c.rbegin(),c.rend(),v);
    if (ri == c.rend()) return c.end();            // uycie c.end() jako znaku "nie znaleziono"
    return prev(ri.base());
}
---------------
template<typename C, Val v>
auto find_last(C& c, Val v) -> decltype(c.begin())
{
    for (auto p = c.rbegin(); p!=c.rend(); ++p) // widzi sekwencj w odwrotnej kolejnoci
        if (*p==v) return --p.base();
    return c.end();                             // uycie c.end() jako znaku "nie znaleziono"
}
---------------
template<typename C>
auto find_last(C& c, Val v) -> decltype(c.begin())
{
    for (auto p = c.end(); p!=c.begin(); ) // przeszukuje wstecz, od end
        if (*--p==v) return p;
    return c.end();                        // uycie c.end() jako znaku "nie znaleziono"
}
---------------
void f(vector<int>& vi)
{
    fill_n(vi.begin(),200,7); // przypisuje 7 do vi[0]..[199]
}
---------------
void g(vector<int>& vi)
{
    fill_n(back_inserter(vi),200,7); // dodaje 200 sidemek na kocu vi
}

---------------
vector<string> v;
back_insert_iterator<vector<string>> p {v};

---------------
vector<string> read_strings(istream&);
auto vs = read_strings(cin);                  // pobiera acuchy

vector<string> vs2;
copy(vs.begin(),vs.end(),back_inserter(vs2)); // kopiuje z vs do vs2

vector<string> vs3;
copy(make_move_iterator(vs2.begin()),make_move_iterator(vs2.end()),back_inserter(vs3)); // przenosi

---------------
template<typename C>
    auto begin(C& c) -> decltype(c.begin());
template<typename C>
    auto begin(const C& c) -> decltype(c.begin());
template<typename C>
    auto end(C& c) -> decltype(c.end());
template<typename C>
    auto end(const C& c) -> decltype(c.end());

template<typename T, size_t N> // dla tablic wbudowanych
    auto begin(T (&array)[N]) -> T*;
template<typename T, size_t N>
    auto end(T (&array)[N]) -> T*;
---------------
template<typename Cont>
void print(Cont& c)
{
    for(auto p=begin(c); p!=end(c); ++p)
        cout << *p << '\n';
}

void f()
{
    vector<int> v {1,2,3,4,5};
    print(v);

    int a[] {1,2,3,4,5};
    print(a);
}
---------------
template<typename T>
Iterator<My_container<T>> begin(My_container<T>& c)
{
    return Iterator<My_container<T>>{&c[0]};           // iterator do pierwszego elementu
}

template<typename T>
Iterator<My_container<T>> end(My_container<T>& c)
{
    return Iterator<My_container<T>>{&c[0]+c.size()};  // iterator do ostatniego elementu
}

---------------
vector<int> v;
//...
sort(v.begin(),v.end(),greater<int>{}); // sortuje v w porzdku malejcym
---------------
vector<int> v;
//...
sort(v.begin(),v.end(),[](int a, int b) { return a>b; }); // sortuje v w porzdku malejcym

---------------
double cube(double);

auto cube2 = bind(cube,2);
---------------
using namespace placeholders;

void f(int,const string&);
auto g = bind(f,2,_1);  // wie pierwszy argument funkcji f() z 2
f(2,"witaj");
g("witaj");             // take wywouje f(2,"hello");
---------------
f(2,"witaj");
bind(f)(2,"witaj");       // take wywouje f(2,"witaj");
bind(f,_1,_2)(2,"witaj"); // take wywouje f(2,"witaj");
bind(f,_2,_1)("witaj",2); // odwrotna kolejno argumentw: take wywouje f(2,"witaj");

auto g = [](const string& s, int i) { f(i,s); } // odwrotna kolejno argumentw
g("witaj",2);                                   // take wywouje f(2,"witaj");
---------------
int pow(int,int);
double pow(double ,double); // funkcja pow() jest przeciona

auto pow2 = bind(pow,_1,2);                            // bd: ktra funkcja pow()?
auto pow2 = bind((double(*)(double ,double))pow,_1,2); // OK (ale brzydkie)
---------------
void incr(int& i)
{
    ++i;
}

void user()
{
    int i = 1;
    incr(i); // i ma warto 2
    auto inc = bind(incr,_1);
    inc(i);  // i pozostaje z wartoci 2; inc(i) zwikszyo lokaln kopi i
}

---------------
void user2()
{
    int i = 1;
    incr(i);     // i ma warto 2
    auto inc = bind(incr,_1);
    inc(ref(i)); // i ma warto 3
}
---------------
void user(Shape* p)
{
    p->draw();
    auto draw = mem_fn(&Shape::draw);
    draw(p);
}
---------------
void draw_all(vector<Shape*>& v)
{
    for_each(v.begin(),v.end(),mem_fn(&Shape::draw));
}
---------------
void draw_all(vector<Shape*>& v)
{
    for_each(v.begin(),v.end(),[](Shape* p) { p->draw(); });
}
---------------
int f1(double);
function<int(double)> fct {f1}; // inicjacja do f1
int f2(int);

void user()
{
    fct = [](double d) { return round(d); }; // przypisuje lambd do fct
    fct = f1;                                // przypisuje funkcj do fct
    fct = f2;                                // bd: niepoprawny typ argumentu
}
---------------
int round(double x) { return static_cast<int>(floor(x+0.5)); } // konwencjonalne zaokrglanie 4/5

function<int(double)> f; // f moe zawiera wszystko, co mona wywoa z typem double i zwraca typ int

enum class Round_style { truncate, round };

struct Round { // obiekt funkcyjny przenoszcy stan
    Round_style s;
    Round(Round_style ss) :s(ss) { }
    int operator()(double x) const { return static_cast<int>((s==Round_style::round) ? 
    ((x+0.5) : x); };
};

void t1()
{
    f = round;
    cout << f(7.6) << '\n';                        // wywoanie przez f funkcji round

    f = Round(Round_style::truncate);
    cout << f(7.6) << '\n';                        // wywoanie obiektu funkcyjnego

    Round_style style = Round_style::round;
    f = [style] (double x){ return static_cast<int>((style==Round_style::round) ? 
    (x+0.5 : x); };

    cout << f(7.6) << '\n';                        // wywoanie lambdy

    vector<double> v {7.6};
    f = Round(Round_style::round);
    std::transform(v.begin(),v.end(),v.begin(),f); // przekazanie do algorytmu

    cout << v[0] << '\n';                          // przeksztacone przez lambd
}
