---------------
template<typename C>
class String {
public:
    String();
    //...
    C& operator[](int n) { return ptr[n]; } // niekontrolowany dostp do elementw
    String& operator+=(C c);                // dodaje c na kocu
private:
    static const int short_max = 15;        // do optymalizacji krtkich acuchw (19.3.3)
    int sz;                                 // liczba elementw C
    char*ptr;
    union {
        int space;                          // nieuywana alokowana przestrze
        C ch[shor t_max+1];                 // zostawia miejsce na kocowe 0
    };
    //...
};
---------------
String<char> cs;
String<unsigned char> us;
String<wchar_t> ws;
struct Jchar { /*...*/}; // japoski znak
String<Jchar> js;
---------------
int main() // liczy wystpienia kadego sowa na wejciu
{
    map<String<char>,int> m;
    for (String<char> buf; cin>>buf;)
        ++m[buf];
    //... drukowanie wyniku...
}
---------------
int main() // liczy wystpienia kadego sowa na wejciu
{
    map<String<Jchar>,int> m;
    for (String<Jchar> buf; cin>>buf;)
        ++m[buf];
    //... drukowanie wyniku...
}
---------------
using string = std::basic_string<char>;
---------------
int main()// liczy wystpienia kadego sowa na wejciu
{
    map<string,int> m;
    for (string buf; cin>>buf;)
        ++m[buf];
    //...drukowanie wyniku...
}
---------------
template<typename C>
String<C>::String()  // konstruktor klasy String<C>
    :sz{0}, ptr{ch}  // krtki acuch: wskanik do ch
{
    ch[0] = {};      // kocowe 0 odpowiedniego typu znakw
}
template<typename C>
String& String<C>::operator+=(C c)
{
    //... dodaje c na kocu tego acucha...
    return *this;
}
---------------
template<typename T>
class String { /*...*/};

class String { /*...*/}; // bd: podwjna definicja
---------------
String<char> cs;

void f()
{
    String<Jchar> js;

    cs = "To implementacja musi wydedukowa, jaki kod trzeba wygenerowa";
}
---------------
template<Container Cont, typename Elem>
    requires Equal_comparable<Cont::value_type ,Elem>() // wymagania dotyczce typw Cont i Elem
int find_index(Cont& c, Elem e);                        // znajduje indeks e w c
---------------
String<char> s1;
String<unsigned char> s2;
String<int> s3;

using Uchar = unsigned char;
using uchar = unsigned char;

String<Uchar> s4;
String<uchar> s5;
String<char> s6;

template<typename T, int N> // 25.2.2
    class Buffer;
Buffer<String<char>,10> b1;
Buffer<char,10> b2;
Buffer<char,20-10> b3;
---------------
Shape* p {new Circle(p,100)};            // Circle* konwertuje si na Shape*
vector<Shape>* q {new vector<Circle>{}}; // bd: brak konwersji vector<Circle>* na vector<Shape>*
vector<Shape> vs {vector<Circle>{}};     // bd: brak konwersji vector<Circle> na vector<Shape>
vector<Shape*> vs {vector<Circle*>{}};   // bd: brak konwersji vector<Circle*> na vector<Shape*>
---------------
template<typename T>
struct Link {
    Link* pre;
    Link* suc // bd skadni: brak rednika
    T val;
};

template<typename T>
class List {
    Link<T>* head;
public:
    List() :head{7} { }                             // bd: inicjacja wskanika wartoci typu int
    List(const T& t) : head{new Link<T>{0,o,t}} { } // bd: niezdefiniowany identyfikator o
    //...
    void print_all() const;
};
---------------
template<typename T>
void List<T>::print_all() const
{
    for (Link<T>* p = head; p; p=p->suc) // p zaley od T
        cout << p->val;                  // << zaley od T
}
---------------
class Rec {
    string name;
    string address;
};
void f(const List<int>& li, const List<Rec>& lr)
{
    li.print_all();
    lr.print_all();
}
---------------
template<typename T>
struct X {
    int m1 = 7;
    T m2;
    X(const T& x) :m2{x} { }
};

X<int> xi {9};
X<string> xs {"Rapperswil"};
---------------
template<typename T>
struct X {
    void mf1() { /*...*/}   // zdefiniowana w klasie
    void mf2();
};

template<typename T>
void X<T>::mf2() { /*...*/} // zdefiniowana poza klas
---------------
template<typename T>
class Vector {
public:
    using value_type = T;
    using iterator = Vector_iter<T>;  // Vector_iter jest zdefiniowana gdzie indziej
    //...
};
---------------
template<typename T>
struct X {
    static constexpr Point p {100,250}; // Point musi by typem literaowym (10.4.3)
    static const int m1 = 7;
    static int m2 = 8;                  // bd: nie const
    static int m3;
    static void f1() { /*...*/}
    static void f2();
};
template<typename T> int X<T>::m1 = 88; // bd: dwa inicjatory
template<typename T> int X<T>::m3 = 99;
template<typename T> void X<T>::f2() { /*...*/}
---------------
template<typename T>
struct X {
    static int a;
    static int b;
};

int* p = &X<int>::a;
---------------
template<typename T>
struct X {
    enum E1 { a, b };
    enum E2; // bd: nieznany typ podstawowy
    enum class E3;
    enum E4 : char;

    struct C1 { /*...*/};
    struct C2;
};

template<typename T>
enum class X<T>::E3 { a, b };  // potrzebne

template<typename T>
enum X<T>::E4 : char { x, y }; // potrzebne

template<typename T>
struct X<T>::C2 { /*...*/};       // potrzebne
---------------
template<typename Scalar>
class complex {
    Scalar re, im;
public:
    complex() :re{}, im{} {}           // konstruktor domylny
    template<typename T>
        complex(T rr, T ii =0) :re{rr}, im{ii} { }

    complex(const complex&) = default; // konstruktor kopiujcy
    template<typename T>
        complex(const complex<T>& c) :re{c.real()}, im{c.imag()} { }
    //...
};
---------------
complex<float> cf;                // warto domylna
complex<double> cd {cf};          // OK: konwersja float na double
complex<float> cf2 {cd};          // bd: brak niejawnej konwersji double->float

complex<float> cf3 {2.0,3.0};     // bd: brak niejawnej konwersji double->float
complex<double> cd2 {2.0F,3.0F};  // OK: konwersja float na double

class Quad {
    // brak konwersji na int
};

complex<Quad> cq;
complex<int> ci {cq}; // bd: brak konwersji Quad na int
---------------
template<typename Scalar>
class complex {  // stary styl
    Scalar re, im;
public:
    complex() :re(0), im(0) { }
    template<typename T>
    complex(T rr, T ii =0) :re(rr), im(ii) { }

    complex(const complex&) = default; // konstruktor kopiujcy
    template<typename T>
    complex(const complex<T>& c) : re(c.real()), im(c.imag()) { }
    //...
};

complex<float> cf4 {2.1,2.9}; // ups! zawenie
complex<float> cf5 {cd};      // ups! zawenie
---------------
class Shape {
    //...
    template<typename T>
        virtual bool intersect(const T&) const =0; // bd: szablon wirtualny
};
---------------
template<typename T, typename Allocator>
class List {
private:
    struct Link {
        T val;
        Link* succ;
        Link* prev;
    };
    //...
};
---------------
template<typename T, typename Allocator>
class List;

template<typename T>
class Link {
    template<typename U, typename A>
        friend class List;
    T val;
    Link* succ;
    Link* prev;
};

template<typename T, typename Allocator>
class List {
    //...
};
---------------
template<typename T, typename A>
class List {
public:
    class Iterator {
        Link<T>* current_position;
    public:
        //... typowy kod iteratora...
    };

    Iterator begin();
    Iterator end();
    //...
};
---------------
void fct(List<int>::Iterator b, List<int>::Iterator e) // bd: List pobiera dwa argumenty
{
    auto p = find(b,e,17);
    //...
}

void user(List<int,My_allocator>& lm, List<int,Your_allocator>& ly)
{
    fct(lm.begin(),lm.end());
    fct(ly.begin(),ly.end());
}
---------------
void fct(List<int,My_allocator>::Iterator b, List<int,My_allocator>::Iterator e)
{
    auto p = find(b,e,17);
    //...
}
---------------
void user(List<int,My_allocator>& lm, List<int,Your_allocator>& ly)
{
    fct(lm.begin(),lm.end());
    fct(ly.begin(),ly.end()); // bd: fct przyjmuje List<int,My_allocator>::Iterator
}
---------------
template<typename T>
struct Iterator {
    Link<T>* current_position;
};

template<typename T, typename A>
class List {
public:
    Iterator<T> begin();
    Iterator<T> end();
    //...
};
---------------
template<typename T> class Matrix;

template<typename T>
class Vector {
    T v[4];
public:
    friend Vector operator*<>(const Matrix<T>&, const Vector&);
    //...
};

template<typename T>
class Matrix {
    Vector<T> v[4];
public:
    friend Vector<T> operator*<>(const Matrix&, const Vector<T>&);
    //...
};
---------------
template<typename T>
Vector<T> operator*(const Matrix<T>& m, const Vector<T>& v)
{
    Vector<T> r;
    //... uycie m.v[i] i v.v[i] w celu uzyskania bezporedniego dostpu do elementw...
    return r;
}
---------------
class C;
using C2 = C;

template<typename T>
class My_class {
    friend C;        // OK: C jest klas
    friend C2;       // OK: C2 jest aliasem klasy
    friend C3;       // bd: brak klasy C3 w zakresie
    friend class C4; // OK: wprowadza now klas C4
};
---------------
template<typename T>
class My_other_class {
    friend T;            // mj argument jest moim przyjacielem!
    friend My_class<T>;  // My_class z argumentem jest moim przyjacielem
    friend class T;      // bd: niepotrzebne sowo "class"
};
---------------
template<typename T, typename A>
class List;

template<typename T>
class Link {
    template<typename U, typename A>
        friend class List;
    //...
};
---------------
template<typename T> void sort(vector<T>&);  // deklaracja

void f(vector<int>& vi, vector<string>& vs)
{
    sort(vi); // sort(vector<int>&);
    sort(vs); // sort(vector<string>&);
}
---------------
template<typename T>
void sort(vector<T>& v) // definicja
    // Sortowanie Shella (Knuth, tom 3, str 84)
{
    const size_t n = v.siz e();

    for (int gap=n/2; 0<gap; gap/=2)
        for (int i=gap; i<n; i++)
            for (int j=i-gap; 0<=j; j-=gap)
                if (v[j+gap]<v[j]) { // zamiana v[j] i v[j+gap]
                    T temp = v[j];
                    v[j] = v[j+gap];
                    v[j+gap] = temp;
                }
}
---------------
if (v[j+gap]<v[j])
    swap(v[j],v[j+gap]);
---------------
template<typename T, typename Compare = std::less<T>>
void sort(vector<T>& v) // definicja
    // Sortowanie Shella (Knuth, tom 3, str. 84)
{
    Compare cmp; // tworzy domylny obiekt klasy Compare
    const size_t n = v.size();

    for (int gap=n/2; 0<gap; gap/=2)
        for (int i=gap; i<n; i++)
            for (int j=i-gap; 0<=j; j-=gap)
                if (cmp(v[j+gap],v[j]))
                    swap(v[j],v[j+gap]);
}
---------------
struct No_case {
    bool operator()(const string& a, const string& b) const; // bez rozrniania wielkoci liter
};

void f(vector<int>& vi, vector<string>& vs)
{
    sort(vi);                        // sort(vector<int>&)
    sort<int,std::greater<int>>(vi); // sort(vector<int>&) przy uyciu greater

    sort(vs);                        // sort(vector<string>&)
    sort<string,No_case>(vs);        // sort(vector<string>&) przy uyciu No_case
}
---------------
template<typename T, int max>
struct Buffer {
    T buf[max];
public:
    //...
};

template<typename T, int max>
T& lookup(Buffer<T,max>& b, const char* p);

string& f(Buffer<string,128>& buf, const char* p)
{
    return lookup(buf,p); // uycie lookup(), gdzie T to string, a max to 128
}
---------------
template<typename T1, typename T2>
pair<T1,T2> make_pair(T1 a, T2 b)
{
    return {a,b};
}

auto x = make_pair(1,2);                      // x to pair<int,int>
auto y = make_pair(string("Nowy Jork"),7.7);  // y to pair<string,double>
---------------
template<typename T>
T* create(); // tworzy obiekt typu T i zwraca wskanik do niego

void f()
{
    vector<int> v;          // klasa, argument szablonowy int
    int* p = create<int>(); // funkcja, argument szablonowy int
    int* q = create();      // bd: nie mona wydedukowa argumentu szablonu
}

---------------
template<typename T, typename U>
void f(const T*,U(*)(U));

int g(int);

void h(const char* p)
{
    f(p,g); // T to char, U to int
    f(p,h); // bd: nie mona wydedukowa U
}
---------------
template<typename T>
void f(T i, T* p);

void g(int i)
{
    f(i,&i);          // OK
    f(i,"Pamitaj!"); // bd niejednoznacznoci: T to int czy const char?
}
---------------
template<typename T>
class Xref {
public:
    Xref(int i, T* p)  // zapisuje wskanik: Xref jest wacicielem
        :index{i}, elem{p}, owned{true}
    {}

    Xref(int i, T& r)  // zapisuje wskanik do r, wacicielem jest kto inny
        :index{i}, elem{&r}, owned{false}
    {}

    Xref(int i, T&& r) // przenosi r do Xref, Xref jest wacicielem
        :index{i}, elem{new T{move(r)}}, owned{true}
    {}

    ~Xref()
    {
        if (owned) delete elem;
    }
    //...
private:
    int index;
    T* elem;
    bool owned;
};
---------------
string x {"Tam i z powrotem"};
Xref<string> r1 {7,"Tutaj"};            // r1 posiada kopi string{"Tutaj"}
Xref<string> r2 {9,x};                  // r2 tylko odwouje si do x
Xref<string> r3 {3,new string{"Tam"}};  // r3 posiada string{"Tam"}
---------------
template<typename T>
    T&& std::forward(typename remove_reference<T>::type& t) noexcept;  // 35.5.1
template<typename T>
    T&& std::forward(typename remove_reference<T>::type&& t) noexcept;

template<typename TT, typename A>
unique_ptr<TT> make_unique(int i, A&& a) // prosta wersja make_shared (34.3.2)
{
    return unique_ptr<TT>{new TT{i,forward<A>(a)}};
}
---------------
auto p1 = make_unique<Xref<string>>(7,"Tutaj");
---------------
auto p2 = make_unique<Xref<string>>(9,x);
---------------
template<typename T>
    T sqrt(T);
template<typename T>
    complex<T> sqrt(complex<T>);
double sqrt(double);

void f(complex<double> z)
{
    sqrt(2);   // sqrt<int>(int)
    sqrt(2.0); // sqrt(double)
    sqrt(z);   // sqrt<double>(complex<double>)
}
---------------
template<typename T>
T max(T,T);

const int s = 7;

void k()
{
    max(1,2);     // max<int>(1,2)
    max('a','b'); // max<char>('a','b')
    max(2.7,4.9); // max<double>(2.7,4.9)
    max(s,7);     // max<int>(int{s},7) (uyta prosta konwersja)

    max('a',1); // bd niejednoznacznoci: max<char,char>() czy max<int,int>()?
    max(2.7,4); // bd niejednoznacznoci: max<double,double>() czy max<int,int>()?
}
---------------
void f()
{
    max<int>('a',1);    // max<int>(int('a'),1)
    max<double>(2.7,4); // max<double>(2.7,double(4))
}
---------------
inline int max(int i, int j) { return max<int>(i,j); }
inline double max(int i, double d) { return max<double>(i,d); }
inline double max(double d, int i) { return max<double>(d,i); }
inline double max(double d1, double d2) { return max<double>(d1,d2); }

void g()
{
    max('a',1); // max(int('a'),1)
    max(2.7,4); // max(2.7,4)
}
---------------
template<typename Iter>
typename Iter::value_type mean(Iter first, Iter last);

void f(vector<int>& v, int* p, int n)
{
    auto x = mean(v.begin(),v.end());  // OK
    auto y = mean(p,p+n);              // bd
}
---------------
int*::value_type mean(int*,int*); // int* nie ma skadowej o nazwie value_type
---------------
template<typename Iter>
typename Iter::value_type mean(Iter first, Iter last); // 1: zwraca redni warto sekwencji

template<typename T>
T mean(T*,T*);                                         // 2: zwraca redni warto tablicy

void f(vector<int>& v, int* p, int n)
{
    auto x = mean(v.begin(),v.end());  // OK: wywoanie 1
    auto y = mean(p,p+n);              // OK: wywoanie 2
}
---------------
int*::value_type mean(int*,int*); // int* nie ma skadowej o nazwie value_type
---------------
template<typename Iter>
Iter mean(Iter first, Iter last) // 1: zwraca iterator do elementu sekwencji zawierajcego redni warto
{
    using Val = typename Iter::value_type;
    //...
}

template<typename T>
T* mean(T*,T*);                  // 2: zwraca wskanik do elementu tablicy zawierajcego warto redni

void f(vector<int>& v, int* p, int n)
{
    auto x = mean(v.begin(),v.end());  // OK: wywoanie 1
    auto y = mean(p,p+n);              // OK: wywoanie 2
}
---------------
template<typename T>
    class B { /*...*/};
template<typename T>
    class D : public B<T> { /*...*/};

template<typename T> void f(B<T>*);

void g(B<int>* pb, D<int>* pd)
{
    f(pb); // oczywicie f<int>(pb)
    f(pd); // f<int>(static_cast<B<int>*>(pd));
           // zastosowana standardowa konwersja D<int>* na B<int>*
}
---------------
template<typename T, typename C>
T get_nth(C& p, int n); // pobiera n-ty element
---------------
struct Index {
    operator int();
    //...
};

void f(vector<int>& v, shor t s, Index i)
{
    int i1 = get_nth<int>(v,2);  // dokadne dopasowanie
    int i2 = get_nth<int>(v,s);  // standardowa konwersja: short na int
    int i3 = get_nth<int>(v,i);  // konwersja uytkownika: Index na int
}
---------------
template<typename T, typename Allocator = allocator<T>> vector;

using Cvec = vector<char>;                // oba argumenty s zwizane

Cvec vc = {'a', 'b', 'c'};                // vc to vector<char,allocator<char>>

template<typename T>
using Vec = vector<T,My_alloc<T>>;        // vector uywajcy mojego alokatora (zwizany jest drugi argument)

Vec<int> fib = {0, 1, 1, 2, 3, 5, 8, 13}; // fib to vector<int,My_alloc<int>>
---------------
vector<char,allocator<char>> vc2 = vc;   // vc2 i vc s tego samego typu
vector<int,My_alloc<int>> verbose = fib; // verbose i fib s tego samego typu
---------------
template<int>
struct int_exact_traits { // idea: int_exact_traits<N>::type jest typem z dokadnie N bitw
    using type = int;
};

template<>
struct int_exact_traits<8> {
    using type = char;
};

template<>
struct int_exact_traits<16> {
    using type = short;
};

template<int N>
using int_exact = typename int_exact_traits<N>::type;  // definicja aliasu dla wygodnej notacji

int_exact<8> a = 7; // int_exact<8> to int z 8 bitami
---------------
// plik out.h:

#include<iostream>

template<typename T>
void out(const T& t)
{
    std::cerr << t;
}
---------------
// plik user1.cpp:

    #include "out.h"
    // uycie out()
---------------
// plik user2.cpp:

    #include "out.h"
    // uycie out()
---------------
// plik outdecl.h:

    template<typename T>
    void out(const T& t);
---------------
// plik out.cpp:

    #include<iostream>

    template<typename T>
    void out(const T& t)
    {
        std::cerr << t;
    }
---------------
// plik user3.cpp:

    #include "out.h"
    // uycie out()
    #include "out.cpp"
---------------
// plik user1.cpp:

    #include "out.h"
    // uycie out()
---------------
// plik user4.cpp:

    #define std MyLib
    #include "out.h"
    // uycie out()
---------------
double accum(const vector<double>& v)
{
    return accumulate(v.begin(),v.end(),0.0);
}
---------------
double accum(const vector<double>& v);