---------------
template<typename X>
class Ct {       // interfejs parametryzowany
    X mem;
public:
    X f();
    int g();
    void h(X);
};

template<>
class Ct<A> {    // specjalizacja (dla A)
    A* mem;      // reprezentacja moe si rni od reprezentacji szablonu podstawowego
public:
    A f();
    int g();
    void h(A);
    void k(int); // dodana funkcja
};

Ct<A> cta;       // specjalizacja dla A
Ct<B> ctb;       // specjalizacja dla B
---------------
class X {
    //...
};

class Cx {             // interfejs wyraony przy uyciu typw w zakresie
    X mem;
public:
    virtual X& f();
    virtual int g();
    virtual void h(X&);
};

class DA : public Cx { // klasa pochodna
public:
    X& f();
    int g();
    void h(X&);
};

class DB : public Cx { // klasa pochodna
    DB* p;             // reprezentacja moe by szersza od bazy
public:
    X& f();
    int g();
    void h(X&);
    void k(int);       // dodana funkcja
};

Cx& cxa {*new DA};     // cxa jest interfejsem do DA
Cx& cxb {*new DB};     // cxb jest interfejsem do DB
---------------
class Shape {
    //...
};

class Circle : public Shape {
    //...
};
---------------
class Triangle : public Shape {
    //...
};

void f(set<Shape*>& s)
{
    //...
    s.insert(new Triangle{p1,p2,p3});
}

void g(set<Circle*>& s)
{
    f(s); // bd niedopasowania typw: s jest set<Circle*>, nie set<Shape*>
}
---------------
void maul(Shape* p, int n) // niebezpieczestwo!
{
    for (int i=0; i!=n; ++i)
        p[i].draw();       // wyglda niewinnie, ale to tylko pozory
}

void user()
{
    Circle image[10];      // obraz skada si z 10 k
    //...
    maul(image,10);        // dziaa na 10 koach
    //...
}

---------------
template<typename T>
class Ptr { // wskanik do T
    T* p;
public:
    Ptr(T*);
    Ptr(const Ptr&);             // konstruktor kopiujcy
    template<typename T2>
    explicit operator Ptr<T2>(); // konwersja Ptr<T> na Ptr<T2>
    //...
};
---------------
void f(Ptr<Circle> pc)
{
    Ptr<Shape> ps {pc};   // powinno dziaa
    Ptr<Circle> pc2 {ps}; // powinno by bdem
}
---------------
template<typename T>
    template<typename T2>
        Ptr<T>::operator Ptr<T2>()
        {
            return Ptr<T2>{p};
        }
---------------
void f(Ptr<Circle> pc)
{
    Ptr<Shape> ps {pc};   // OK: mona przekonwertowa Circle* na Shape*
    Ptr<Circle> pc2 {ps}; // bd: nie mona przekonwertowa Shape* na Circle*
}
---------------
template<typename T, typename T2> // bd
Ptr<T>::operator Ptr<T2>()
{
    return Ptr<T2>{p};
}
---------------
template<typename Color_scheme, typename Canvas>  // wtpliwy przykad
class Shape {
    //...
};

template<typename Color_scheme, typename Canvas>
class Circle : public Shape {
    //...
};

template<typename Color_scheme, typename Canvas>
class Triangle : public Shape {
    //...
};

void user()
{
    auto p = new Triangle<RGB,Bitmapped>{{0,0},{0,60},{30,sqrt(60*60-30*30)}};
    //...
}
---------------
class Shape {
    template<typename Color_scheme , typename Canvas>
        void configure(const Color_scheme&, const Canvas&);
    //...
};
---------------
template<typename T>
class Vector<T*>
    : private Vector<void*>
{
    //...
};
---------------
template<typename N>
struct Node_base { // nie wie o Val (dane uytkownika)
    N* left_child;
    N* right_child;

    Node_base();

    void add_left(N* p)
    {
        if (left_child==nullptr)
            left_child = p;
        else
            //...
    }
    //...
};

template<typename Val>
struct Node : Node_base<Node<Val>> { // uycie klasy pochodnej jako czci jej wasnej bazy
    Val v;
    Node(Val vv);
    //...
};
---------------
struct Node_double  {
    double val;
    Node_double* left_child;
    Node_double* right_child;
};
---------------
using My_node = Node<double>;

void user(const vector<double>& v)
{
    My_node root;
    int i = 0;

    for (auto x : v) {
        auto p = new My_node{x};
        if (i++%2) // wybr miejsca wstawiania
            root.add_left(p);
        else
            root.add_right(p);
    }
}
---------------
template<typename N>
struct Node_base {
    static_assert(Totally_ordered<N>(), "Node_base: N musi mie operator <");

    N* left_child;
    N* right_child;
    Balancing_info bal;

    Node_base();

    void insert(N& n)
    {
        if (n<left_child)
            //... jakie dziaania...
        else
            //... jakie inne dziaania...
    }
    //...
};
---------------
template<typename Val, typename Balance>
struct Search_node : public Node_base<Search_node<Val, Balance>, Balance>
{
    Val val; // dane uytkownika
    Search_node(Val v): val(v) {}
};
---------------
template<typename N, typename Balance>
struct Node_base : Balance {
    N* left_child;
    N* right_child;

    Node_base();

    void insert(N& n)
    {
        if (this->compare(n,left_child))  // uywa compare() z Balance
            //... jakie dziaania...
        else
            //... jakie inne dziaania...
    }
    //...
};
---------------
struct Red_black_balance {
    // dane i operacje potrzebne do implementacji drzew czerwono-czarnych
};

template<typename T>
using Rb_node = Search_node<T,Red_black_balance>; // alias typu dla drzew czerwono-czarnych

Rb_node<double> my_root;  // drzewo czerwono-czarne wartoci typu double

using My_node = Rb_node<double>;

void user(const vector<double>& v)
{
    for (auto x : v)
    my_root.insert(*new My_node{x});
}
---------------
template<typename N, typename Balance>
struct Node_base : Balance {
    //...
};

template<typename Val, typename Balance>
struct Search_node
    : public Node_base<Search_node<Val, Balance>, Balance>
{
    //...
};
---------------
template<typename N>
struct Node_base : N::balance_type { // uywa skadowej balance_type typu N
    //...
};

template<typename Val, typename Balance>
struct Search_node
    : public Node_base<Search_node<Val,Balance>>
{
using balance_type = Balance;
    //...
};
---------------
Var -> Decl -> Stmt -> Expr -> Node
---------------
impl::Var -> impl::Decl -> impl::Stmt -> impl::Expr -> impl::Node
---------------
impl::Var ->
    impl::Decl<ipr::Var> ->
        impl::Stmt<ipr::Var> ->
            impl::Expr<ipr::Var> ->
                impl::Node<ipr::Var> ->
                    ipr::Var ->
                        ipr::Decl ->
                            ipr::Stmt ->
                                ipr::Expr ->
                                    ipr::Node
---------------
struct ipr::Node {
    const int node_id;
    const Category_code category;

    virtual void accept(Visitor&) const = 0; // punkt zaczepienia dla klas wizytujcych
protected:
    Node(Category_code);
};
---------------
struct ipr::Expr : Node {
    virtual const Type& type() const = 0;
protected:
    Expr(Category_code c) : Node(c) { }
};
---------------
struct ipr::Stmt : Expr {
    virtual const Unit_location& unit_location() const = 0;     // wiersz w pliku
    virtual const Source_location& source_location() const = 0; // plik

    virtual const Sequence<Annotation>& annotation() const = 0;
protected:
    Stmt(Category_code c) : Expr(c) { }
};
---------------
struct ipr::Decl : Stmt {
    enum Specifier { /* klasa przechowujca, wirtualno, kontrola dostpu itd.*/};

    virtual Specifier specifiers() const = 0;
    virtual const Linkage& lang_linkage() const = 0;

    virtual const Name& name() const = 0;

    virtual const Region& home_region() const = 0;
    virtual const Region& lexical_region() const = 0;

    virtual bool has_initializer() const = 0;
    virtual const Expr& initializer() const = 0;

    //...
protected:
    Decl(Category_code c) : Stmt(c) { }
};
---------------
struct ipr::Var : Category<var_cat, Decl> {
};
---------------
template<Category_code Cat, typename T = Expr>
struct ipr::Category:T{
protected:
    Category() : T(Cat) { }
};
---------------
template<typename T>
struct impl::Node : T {
    using Interface = T; // czyni typ argumentu szablonu dostpnym dla uytkownikw
    void accept(ipr::Visitor& v) const override { v.visit(*this); }
};
---------------
template<typename Interface>
struct impl::Expr : impl::Node<Interface> {
    const ipr::Type* constraint; // ograniczenie jest typem wyraenia

    Expr() : constraint(0) { }

    const ipr::Type& type() const override { return *util::check(constraint); }
};
---------------
template<typename S>
struct impl::Stmt : S {
    ipr::Unit_location unit_locus;   // logiczna pozycja w jednostce translacji
    ipr::Source_location src_locus;  // plik rdowy, wiersz i kolumna
    ref_sequence<ipr::Annotation> notes;

    const ipr::Unit_location& unit_location() const override { return unit_locus; }
    const ipr::Source_location& source_location() const override { return src_locus; }
    const ipr::Sequence<ipr::Annotation>& annotation() const override { return notes; }
};
---------------
template<typename D>
struct impl::Decl : impl::Stmt<impl::Expr<D>> { // uywa implementacji Stmt i Expr
    basic_decl_data<D> decl_data;
    ipr::Named_map* pat;
    val_sequence<ipr::Substitution> args;

    Decl() : decl_data(0), pat(0) { }

    const ipr::Sequence<ipr::Substitution>& substitutions() const { return args; }
    const ipr::Named_map& generating_map() const override { return *util::check(pat); }
    const ipr::Linkage& lang_linkage() const override;
    const ipr::Region& home_region() const override;
};
---------------
struct Var : impl::Decl<ipr::Var> {
    const ipr::Expr* init;
    const ipr::Region* lexreg;

    Var();

    bool has_initializer() const override;
    const ipr::Expr& initializer() const override;
    const ipr::Region& lexical_region() const override;
};