---------------
double add_all(double*array, int n)
    // jeden konkretny algorytm dziaajcy na tablicy wartoci typu double
{
    double s {0};
    for (int i = 0; i<n; ++i)
        s=s+array[i];
    return s;
}
---------------
struct Node {
    Node* next;
    int data;
};

int sum_elements(Node* first, Node* last)
    // inny konkretny algorytm dziaajcy na licie wartoci typu int
{
    int s = 0;
    while (first!=last) {
        s += first->data;
        first = first->next;
    }
    return s;
}
---------------
// pseudokod:

T suma(dane)
    // parametryzacja typem wartoci i kontenera
{
    Ts=0
    dopki (nie koniec) {
        s=s+bieca warto
        pobierz nastpny element
    }
    zwr s
}
---------------
// konkretny kod przypominajcy zawarto biblioteki STL:
template<typename Iter, typename Val>
Val sum(Iter first, Iter last)
{
    Vals=0;
    while (first!=last) {
        s = s + *first;
        ++first;
    }
    return s;
}
---------------
double ad[] = {1,2,3,4};
double s = sum<double*,double>(ad,ad+4);
---------------
struct Node { Node* next; int data; };
struct Node_iter { Node* pos; };

Node_iter operator++(Node_iter& p) { return p.pos=p.pos->next; }
int operator*(Node_iter p) { return p.pos->data; }
bool operator!=(Node_iter p, Node_iter q) { return p.pos != q.pos; }

void test(Node* lst)
{
    int s = sum<Node_iter,int>(lst,nullptr);
}
---------------
template<typename Iter, typename Val>
Val accumulate(Iter first, Iter last, Val s)
{
    while (first!=last) {
        s = s + *first;
        ++first;
    }
    return s;
}

double ad[] = {1,2,3,4};
double s1 = accumulate(ad,ad+4,0.0);  // akumulacja w double
double s2 = accumulate(ad,ad+4,0);    // akumulacja w int
---------------
template<typename Iter, typename Val, typename Oper>
Val accumulate(Iter first, Iter last, Val s, Oper op)
{
    while (first!=last) {
        s = op(s,*first);
        ++first;
    }
    return s;
}
---------------
double ad[] = {1,2,3,4};
double s1 = accumulate(ad,ad+4,0.0,std::plus<double>{});  // jak wczeniej
double s2 = accumulate(ad,ad+4,1.0,std::multiplies<double>{});
---------------
template<typename C>
class String {
    //...
};
---------------
template<typename T>
bool operator==(const String<T>& s1, const String<T>& s2)
{
    if (s1.size()!=s2.size()) return false;
    for (auto i = 0; i!=s1.size(); ++i)
        if (s1[i]!=s2[i]) return false;
    return true;
}
---------------
enum class rsp { kamie, noyce, papier };
---------------
template<typename Node, typename Balance>
struct node_base { // podstawa drzewa zrwnowaonego
    //...
}
---------------
struct Red_black_balance {
    //...
    template<typename Node> static void add_fixup(Node* x);
    template<typename Node> static void touch(Node* x);
    template<typename Node> static void detach(Node* x);
};
---------------
template<typename C>
class String {
    static_assert(Ordered<C>(),"Typ znakw String nie jest porzdkowany");
    //...
};
---------------
template<Ordered C>
class String {
    //...
};
---------------
template<typename T>
constexpr bool Ordered()
{
    return Regular<T>() && Totally_ordered<T>();
}
---------------
template<typename T>
constexpr bool Totally_ordered()
{
    return Equality_comparable<T>()  // has == i !=
        && Has_less<T>() && Boolean<Less_result<T>>()
        && Has_greater<T>() && Boolean<Greater_result<T>>()
        && Has_less_equal<T>() && Boolean<Less_equal_result<T>>()
        && Has_greater_equal<T>() && Boolean<Greater_equal_result<T>>();
    }

template<typename T>
constexpr bool Equality_comparable()
{
    return Has_equal<T>() && Boolean<Equal_result<T>>()
        && Has_not_equal<T>() && Boolean<Not_equal_result<T>>();
}
---------------
template<typename T>
constexpr bool Regular()
{
    return Semiregular<T>() && Equality_comparable<T>();
}
---------------
template<typename T>
constexpr bool Semiregular()
{
    return Destructible<T>()
        && Default_constructible<T>()
        && Move_constructible<T>()
        && Move_assignable<T>()
        && Copy_constructible<T>()
        && Copy_assignable<T>();
}
---------------
template<typename C>
ostream& operator<<(ostream& out, String<C>& s)
{
    static_assert(Streamable<C>(),"Znaki acucha nie s strumieniowalne");
    out << '"'; // znak w podwjnym cudzysowie
    for (int i=0; i!=s.size(); ++i)
        cout << s[i];
    out << '"';
}
---------------
template<typename T>
constexpr bool Streamable()
{
    return Input_streamable<T>() && Output_streamable<T>();
}
---------------
static_assert(Ordered<std::string>,"std::string nie jest Ordered");  // sukces
static_asser t(Ordered<String<char>>,"String<char> nie jest Ordered");  // poraka
---------------
template<typename C>
bool operator<(const String<C>& s1, const String<C>& s2)
{
    static_asser t(Ordered<C>(),"Typ znakw acucha nie jest uporzdkowany");
    return std::lexicographical_compare(  // 32.6.5
                    s1.begin(), s1.end(),
                    s2.begin(), s2.end()
                );
}
---------------
template<typename T>
bool Copy_equality(T x)              // semantyka konstrukcji z kopiowaniem
{
    return T{x}==x;                  // kopia jest rwna oryginaowi
}

template<typename T>
bool Copy_assign_equality(T x, T& y) // semantyka przypisania
{
    return (y=x, y==x);              // wynik przypisania jest rwny rdu przypisania
}
---------------
template<typename T>
bool Move_effect(T x, T& y)              // semantyka przenoszenia y do x
{
    return (x==y ? (x==T{std::move(y)}) : true) && can_destroy(y);
}

template<typename T>
bool Move_assign_effect(T x, T& y, T& z) // semantyka przypisania przenoszcego y do x
{
    return (y==z ? (x=std::move(y), x==z) : true) && can_destroy(y);
}
---------------
template<typename Iter, typename Val>
Iter find(Iter b, Iter e, Val x);
---------------
template<typename T, typename U>
constexpr bool Equality_comparable(T, U)
{
    return Common<T,U>()
        && Totally_ordered<T>()
        && Totally_ordered<U>()
        && Totally_ordered<Common_type<T,U>>()
        && Has_less<T,U>() && Boolean<Less_result<T,U>>()
        && Has_less<U,T>() && Boolean<Less_result<U,T>>()
        && Has_greater<T,U>() && Boolean<Greater_result<T,U>>()
        && Has_greater<U,T>() && Boolean<Greater_result<U,T>>()
        && Has_less_equal<T,U>() && Boolean<Less_equal_result<T,U>>()
        && Has_less_equal<U,T>() && Boolean<Less_equal_result<U,T>>()
        && Has_greater_equal<T,U>() && Boolean<Greater_equal_result<T,U>>()
        && Has_greater_equal<U,T>() && Boolean<Greater_equal_result<U,T>>();
};
---------------
template<typename Iter, typename Val>
Iter find(Iter b, Iter e, Val x)
{
    static_assert(Input_iterator<Iter>(),"find() wymaga operatora wejciowego");
    static_assert(Equality_comparable<Value_type<Iter>,Val>(),
                    "Typy argumentw find() musz si zgadza");
    while (b!=e) {
        if (*b==x) return b;
        ++b;
    }
    return b;
}
---------------
template<int N>
constexpr bool Small_size()
{
    return N<=8;
}
---------------
constexpr int stack_limit = 2048;

template<typename T,int N>
constexpr bool Stackable()  // T jest typem regularnym i N elementw typu T zmieci si na niewielkim stosie
{
    return Regular<T>() && sizeof(T)*N<=stack_limit;
}
---------------
template<typename T, int N>
struct Buffer {
    //...
};

template<typename T, int N>
void fct()
{
    static_assert(Stackable<T,N>(),"Bufor fct() nie mieci si na stosie");
    Buffer<T,N> buf;
    //...
}
---------------
template<typename Iter, typename Val>
Iter find(Iter b, Iter e, Val x)
{
    static_assert(Input_iterator<Iter>(),"find(): Iter nie jest iteratorem jednokierunkowym");
    static_assert(Equality_comparable<Value_type<Iter>,Val>),
                    "find(): typ wartoci nie odpowiada iteratorowi");
    while (b!=e) {
        if (*b==x) return b;
        b = b+1; // uwaga: nie ++b
    }
    return b;
}
---------------
void f(list<int>& lst, vector<string>& vs)
{
    auto p = find(lst.begin(),lst.end(),1209);       // bd: list nie ma operatora +
    auto q = find(vs.begin(),vs.end(),"Cambridge");  // OK: vector ma operator +
    //...
}
---------------
template<typename Val>
struct Forward {      // do sprawdzania find()
    Forward();
    Forward(const Forward&);
    Forward operator=(const Forward&);
    bool operator==(const Forward&);
    bool operator!=(const Forward&);
    void operator++();
    Val& operator*(); // uproszczenie: nie obsuguje porednika dla Val
};

template<typename Val>
using Value_type<Forward<Val>> = Val;  // uproszczenie; zobacz 28.2.4

void f()
{
    Forward<int> p = find(Forward<int>{},Forward<int>{},7);
}