---------------
class X;
X* p; // OK: definicja X nie jest potrzebna
X a;  // bd: potrzebna definicja X
---------------
template<typename T>
class Link {
    Link* suc; // OK: definicja Link nie jest jeszcze potrzebna
    //...
};

Link<int>* pl; // konkretyzacja Link<int> nie jest jeszcze potrzebna

Link<int> lnk; // teraz konieczna jest konkretyzacja Link<int>
---------------
template<typename T>
class List {
    //...
    void sort();
};

class Glob {
    //... brak operatorw porwnywania...
};

void f(List<Glob>& lb, List<string>& ls)
{
    ls.sort();
    //... uycie operacji na lb, ale nie lb.sort()...
}
---------------
template class vector<int>;                 // klasa
template int& vector<int>::operator[](int); // funkcja skadowa
template int convert<int,double>(double);   // funkcja nieskadowa
---------------
template vector<int>::operator[]; // bd skadni
template convert<int,double>;     // bd skadni
---------------
template int convert<int,double>(double); // OK (nadmiar)
template int convert<int>(double);        // OK
---------------
#include "MyVector.h"

extern template class MyVector<int>;  // wycza niejawn konkretyzacj
                                      // gdzie indziej jest ona wykonana jawnie
void foo(MyVector<int>& v)
{
    //... uycie wektora...
}
---------------
#include "MyVector.h"

template class MyVector<int>;  // konkretyzacja w tej jednostce translacji; uycie tego miejsca konkretyzacji
---------------
bool tracing;
template<typename T>
T sum(std::vector<T>& v)
{
    T t {};
    if (tracing)
        cerr << "sum(" << &v << ")\n";
    for (int i = 0; i!=v.size(); ++i)
        t=t+v[i];
    return t;
}

//...

#include<quad.h>

void f(std::vector<Quad>& v)
{
    Quad c = sum(v);
}
---------------
Quad operator+(Quad,Quad);
---------------
template<typename T>
int f(T a)
{
    return g(a); // OK: a jest nazw zalen, a wic g te ni jest
}

class Quad { /*...*/};
int g(Quad);

int z = f(Quad{2}); // g z funkcji f jest zwizana z g(Quad)
---------------
class Quad { /*...*/};
template<typename T>
int ff(T a)
{
    return gg(Quad{1});  // bd: brak gg() w zakresie, a gg(Quad{1}) nie zaley od T
}

int gg(Quad);

int zz = ff(Quad{2});
---------------
template<typename Container>
void fct(Container& c)
{
    Container::value_type v1 = c[7];          // bd skadni: value_type nie powinna by nazw typu
    typename Container::value_type v2 = c[9]; // OK: value_type powinna by nazw typu
    auto v3 = c[11];                          // OK: niech kompilator wydedukuje
    //...
}
---------------
template<typename T>
using Value_type = typename T::value_type;

template<typename Container>
void fct2(Container& c)
{
    Value_type<Container> v1 = c[7]; // OK
    //...
}
---------------
class Pool { // jaki alokator
public:
    template<typename T> T* get();
    template<typename T> void release(T*);
    //...
};

template<typename Alloc>
void f(Alloc& all)
{
    int* p1 = all.get<int>();           // bd skadni: get nie powinna by nazw szablonu
    int* p2 = all.template get<int>();  // OK: get() powinna by szablonem
    //...
}

void user(Pool& pool)
{
    f(pool);
    //...
}
---------------
int x;
template<typename T>
T f(T a)
{
    ++x;      // OK: x jest w zakresie
    ++y;      // bd: brak y w zakresie oraz y nie zaley od T
    return a; // OK: a jest nazw zalen
}

int y;

int z = f(2);
---------------
void g(double);
void g2(double);

template<typename T>
int ff(T a)
{
    g2(2); // wywoanie g2(double);
    g3(2); // bd: brak g3() w zakresie
    g(a);  // wywoanie g(double); g(int) nie ma w zakresie
    //...
}

void g(int);
void g3(int);

int x = ff(5);
---------------
void g(int);
template<typename T>
void f(T a)
{
    g(a); // g jest wizana w miejscu konkretyzacji
}

void h(int i)
{
    extern void g(double);
    f(i);
}
// miejsce konkretyzacji f<int>
---------------
void g(int);
template<typename T>
void f(T a)
{
    g(a);            // g jest wizana w miejscu konkretyzacji
    if (a>1) h(a-1); // h jest wizana w miejscu konkretyzacji
}

void h(int i)
{
    extern void g(double);
    f(i);
}
// miejsce konkretyzacji f<int>
---------------
template<typename T>
class Container {
    vector<T> v;  // elementy
    //...
public:
    void sort();  // sortuje elementy
    //...
};

// miejsce konkretyzacji Container<int>
void f()
{
    Container<int> c; // miejsce uycia
    c.sort();
}
---------------
void fff()
{
    struct S { int a,b; };
    vector<S> vs;
    //...
}
---------------
template<typename T>
void print_sorted(vector<T>& v)
{
    sort(v.begin(),v.end());
    for (const auto& x : v)
        cout << x << '\n';
}

void use(vector<string>& vec)
{
    //...
    print_sorted(vec); // sortuje przy uyciu funkcji std::sort, a potem drukuje przy uyciu funkcji std::cout
}
---------------
template<typename T, typename S>
void print_sorted(vector<T>& v, S sort, ostream& os)
{
    sort(v.begin(),v.end());
    for (const auto& x : v)
        os << x << '\n';
}

void fct(vector<string>& vec)
{
    //...
    using Iter = decltype(vec.begin());  // typ iteratora klasy vec
    print_sorted(vec,std::sort<Iter>,std::cout);
}
---------------
void f(int); // tutaj zajmuj si liczbami typu int

namespace N {
    class X { };
    char g(X,int);
}

template<typename T>
char ff(T t, double d)
{
    f(d);          // f jest zwizana z f(int)
    return g(t,d); // g moe by zwizana z g(X,int)
}

auto x1 = ff(N::X{},1.1); // ff<N::X,double>; moe wiza g do N::g(X,int), skracajc 1.1 do 1

namespace N {             // otwarcie przestrzeni nazw N w celu dodania obsugi typu double
    double g(X,double);
}

auto x2 = ff(N::X{},2.2); // ff<N::X,double>; wie g do N::g(X,double); najlepsze dopasowanie
---------------
namespace N {
    class A { /*...*/};
    char f(A);
}

char f(int);

template<typename T>
char g(T t)
{
    return f(t);     // wybiera f() w zalenoci od T
}

char f(double);

char c1 = g(N::A()); // powoduje wywoanie N::f(N::A)
char c2 = g(2);      // powoduje wywoanie f(int)
char c3 = g(2.1);    // powoduje wywoanie f(int); f(double) nie jest brana pod uwag
---------------
#include <valarray> // uwaga: brak "using namespace std;"

valarray<double> fct(valarray<double> v1, valarray<double> v2, double d)
{
    return v1+d*v2; // OK dziki ADL
}
---------------
#include<vector>
#include<algorithm>
//...

namespace User {
    class Customer { /*...*/};
    using Index = std::vector<Customer*>;

    void copy(const Index&, Index&, int deep); // gboka lub pytka kopia w zalenoci od wartoci deep

    void algo(Index& x, Index& y)
    {
        //...
        copy(x,y,false); // bd
    }
}
---------------
template<typename In, typename Out>
Out copy(In,In,Out);
---------------
template<typename In, typename Out>
Out copy(In p1, In p2, Out q)
{
    static_assert(Input_iterator<In>(), "copy(): In nie jest iteratorem wejciowym");
    static_assert(Output_iterator<Out>(), "copy(): Out nie jest iteratorem wyjciowym");
    static_assert(Assignable<Value_type<Out>,Value_type<In>>(), "copy(): niedopasowanie 
    (typu wartoci");
    //...
}
---------------
template<typename In, typename Out,
         typename = Enable_if<Input_iterator<In>()
                           && Output_iterator<Out>()
                           && Assignable<Value_type<Out>,Value_type<In>>()>>
Out copy(In p1, In p2, Out q)
{
    //...
}
---------------
void User::algo(Index& x, Index& y)
{
    User::copy(x,y,false);  // OK
    //...
    std::swap(*x[i],*x[j]); // OK: brana pod uwag jest tylko funkcja std::swap
}
---------------
template<typename Range, typename Op>
void apply(const Range& r, Op f)
{
    using std::begin;
    using std::end;
    for (auto& x : r)
        f(x);
}
---------------
void g(int);

struct B {
    void g(char);
    void h(char);
};

template<typename T>
class X : public B {
public:
    void h(int);
    void f()
    {
        g(2); // wywoanie B::g(char)
        h(2); // wywoanie X::h(int)
    }
    //...
};
---------------
void g(int);

struct B {
    void g(char);
    void h(char);
};

template<typename T>
class X : public T {
public:
    void f()
    {
        g(2); // wywoanie ::g(int)
    }
    //...
};

void h(X<B> x)
{
    x.f();
}
---------------
void g(int);
void g2(int);

struct B {
    using Type = int;
    void g(char);
    void g2(char);
};

template<typename T>
class X : public T {
public:
    typename T::Type m; // OK
    Type m2;            // bd (brak Type w zakresie)

    using T::g2();      // dodanie T::g2() do zakresu

    void f()
    {
        this->g(2);     // wywoanie T::g
        g(2);           // wywoanie ::g(int); zdziwiony?
        g2(2);          // wywoanie T::g2
    }
    //...
};

void h(X<B> x)
{
    x.f();
}
---------------
template<typename T>
class Matrix_base { // pami dla macierzy, operacje wszystkich elementw
    //...
    int size() const { return sz; }
protected:
    int sz;   // liczba elementw
    T* elem;  // elementy macierzy
};

template<typename T, int N>
class Matrix : public Matrix_base<T> { // macierz N-wymiarowa
    //...
    T* data() // zwraca wskanik do kontenera elementw
    {
        return this->elem;
    }
};