zoukankan      html  css  js  c++  java
  • 6.4-数据结构&算法-模板/函数模板/类模板/特化

    一、为什么要有模板?
    将类型参数化,可以实现算法与类型的分离,编写针对类型更加抽象的函数或者类。
     
    二、函数模板
    通用定义:
    template<typename 类型形参1, ...>
    返回类型 函数模板名 (形参表) { ... }
    特化定义:
    template<>
    返回类型 函数模板名<类型实参1, ...> (形参表) { ... }
     
    三、类模板
    通用定义:
    template<typename 类型形参1, ...>
    class 类模板名 { ... };
    全类特化:
    template<>
    class 类模板名<类型实参1, ...> { ... };
    成员特化:
    template<>
    返回类型 类模板名<类型实参1, ...>::成员函数名 (形参表) { ... }
     
    四、局部特化
     
    五、非类型参数和缺省参数
    1.非类型参数的实参仅限于常量或者常量表达式。
    2.无论类型参数还是非类型参数都可以带有缺省值,而且和函数的缺省参数一样,模板的缺省参数也必须靠右。
     
    六、有关模板的其它问题
    1.从模板继承
    2.向模板派生
    3.模板中模板成员
    1)模板型成员变量
    2)模板型成员函数
    3)模板型成员类型
    4.模板型模板实参
     
    七、容器和迭代器

    arg.cpp
    #include <iostream>
    using namespace std;
    template<typename T>
    class A {
    public:
        A (const T& t) : m_t (t) {}
        T m_t;
    };
    template<typename X, typename Z,
        template<typename T> class Y>
    class B {
    public:
        B (const X& i, const Z& s) :
            m_i (i), m_s (s) {}
        Y<X> m_i;
        Y<Z> m_s;
    };
    int main (void) {
        B<int, string, A> b (100, "hello");
        cout << b.m_i.m_t << ' ' << b.m_s.m_t << endl;
        return 0;
    }

    array.cpp

    #include <iostream>
    using namespace std;
    template<typename T = int, size_t S = 5>
    class Array {
    public:
        T& operator[] (size_t i) {
            return m_array[i];
        }
        const T& operator[] (size_t i) const {
            return const_cast<Array&> (*this) [i];
        }
        size_t size (void) const {
            return S;
        }
        friend ostream& operator<< (ostream& os,
            const Array& arr) {
            for (size_t i = 0; i < arr.size (); ++i)
                os << '(' << arr.m_array[i] << ')';
            return os;
        }
    private:
        T m_array[S];
    };
    int main (void) {
        const /*volatile*/ int x = 3, y = 7;
        Array<int, x+y> arr;
        for (size_t i = 0; i < arr.size (); ++i)
            arr[i] = i;
        cout << arr << endl;
        Array<Array<int, 4>, 3> m;
        for (size_t i = 0; i < m.size (); ++i)
            for (size_t j = 0; j < m[i].size (); ++j)
                m[i][j] = i * m[i].size () + j;
        cout << m << endl;
        Array<double> a2;
        Array<> a3;
        return 0;
    }

    cmp.cpp

    #include <iostream>
    #include <cstring>
    using namespace std;
    // 通用模板
    template<typename T>
    class Comparator {
    public:
        Comparator (T x, T y) : m_x (x), m_y (y) {}
        T min (void) const {
            return m_x < m_y ? m_x : m_y;
        }
        T max (void) const {
            return m_x > m_y ? m_x : m_y;
        }
    private:
        T m_x;
        T m_y;
    };
    /*
    // 针对char*的全模板特化
    template<>
    class Comparator<char*> {
    public:
        Comparator (char* x, char* y) :
            m_x (x), m_y (y) {}
        char* min (void) const {
            return strcmp (m_x, m_y) < 0 ? m_x : m_y;
        }
        char* max (void) const {
            return strcmp (m_x, m_y) > 0 ? m_x : m_y;
        }
    private:
        char* m_x;
        char* m_y;
    };
    */
    // 针对char*的成员函数特化
    template<>
    char* Comparator<char*>::min (void) const {
        return strcmp (m_x, m_y) < 0 ? m_x : m_y;
    }
    template<>
    char* Comparator<char*>::max (void) const {
        return strcmp (m_x, m_y) > 0 ? m_x : m_y;
    }
    int main (void) {
        cout << "输入两个整数:" << flush;
        int nx, ny;
        cin >> nx >> ny;
        Comparator<int> cn (nx, ny);
        cout << "最小值:" << cn.min () << endl;
        cout << "最大值:" << cn.max () << endl;
        cout << "输入两个字符串:" << flush;
        string sx, sy;
        cin >> sx >> sy;
        Comparator<string> cs (sx, sy);
        cout << "最小值:" << cs.min () << endl;
        cout << "最大值:" << cs.max () << endl;
        cout << "输入两个字符串:" << flush;
        char cx[256], cy[256];
        cin >> cx >> cy;
        Comparator<char*> cc (cx, cy);
        cout << "最小值:" << cc.min () << endl;
        cout << "最大值:" << cc.max () << endl;
        return 0;
    }

    inher.cpp

    #include <iostream>
    using namespace std;
    template<typename T>
    class A {
    public:
        A (const T& t) : m_t (t) {}
        T m_t;
    };
    template<typename T, typename Y>
    class B : public A<T> {
    public:
        B (const T& t, const Y& y) :
            A<T> (t), m_y (y) {}
        Y m_y;
    };
    int main (void) {
        B<int, string> b (100, "hello");
        cout << b.m_t << ' ' << b.m_y << endl;
        return 0;
    }

    inter.cpp

    #include <iostream>
    using namespace std;
    template<typename T>
    class A {
    public:
        class B {};
    };
    template<typename T>
    void foo (void) {
        typename A<T>::B b;
    }
    int main (void) {
        foo<int> ();
        return 0;
    }

    list.cpp

    #include <iostream>
    #include <stdexcept>
    #include <cstring>
    using namespace std;
    // 双向线性链表容器模板
    template<typename T>
    class List {
    public:
        // 构造、析构、拷贝构造、拷贝赋值
        List (void) : m_head (NULL), m_tail (NULL) {}
        ~List (void) {
            clear ();
        }
        List (const List& that) : m_head (NULL),
            m_tail (NULL) {
            for (Node* node = that.m_head; node;
                node = node->m_next)
                push_back (node->m_data);
        }
        List& operator= (const List& that) {
            if (&that != this) {
                List list (that);
                swap (m_head, list.m_head);
                swap (m_tail, list.m_tail);
            }
            return *this;
        }
        // 获取首元素
        T& front (void) {
            if (empty ())
                throw underflow_error ("链表下溢!");
            return m_head->m_data;
        }
        const T& front (void) const {
            return const_cast<List*> (this)->front ();
        }
        // 向首部压入
        void push_front (const T& data) {
            m_head = new Node (data, NULL, m_head);
            if (m_head->m_next)
                m_head->m_next->m_prev = m_head;
            else
                m_tail = m_head;
        }
        // 从首部弹出
        void pop_front (void) {
            if (empty ())
                throw underflow_error ("链表下溢!");
            Node* next = m_head->m_next;
            delete m_head;
            m_head = next;
            if (m_head)
                m_head->m_prev = NULL;
            else
                m_tail = NULL;
        }
        // 获取尾元素
        T& back (void) {
            if (empty ())
                throw underflow_error ("链表下溢!");
            return m_tail->m_data;
        }
        const T& back (void) const {
            return const_cast<List*> (this)->back ();
        }
        // 向尾部压入
        void push_back (const T& data) {
            m_tail = new Node (data, m_tail);
            if (m_tail->m_prev)
                m_tail->m_prev->m_next = m_tail;
            else
                m_head = m_tail;
        }
        // 从尾部弹出
        void pop_back (void) {
            if (empty ())
                throw underflow_error ("链表下溢!");
            Node* prev = m_tail->m_prev;
            delete m_tail;
            m_tail = prev;
            if (m_tail)
                m_tail->m_next = NULL;
            else
                m_head = NULL;
        }
        // 删除所有匹配元素
        void remove (const T& data) {
            for (Node* node = m_head, *next; node;
                node = next) {
                next = node->m_next;
                if (equal (node->m_data, data)) {
                    if (node->m_prev)
                        node->m_prev->m_next =
                            node->m_next;
                    else
                        m_head = node->m_next;
                    if (node->m_next)
                        node->m_next->m_prev =
                            node->m_prev;
                    else
                        m_tail = node->m_prev;
                    delete node;
                }
            }
        }
        // 清空
        void clear (void) {
            for (Node* next; m_head; m_head = next) {
                next = m_head->m_next;
                delete m_head;
            }
            m_tail = NULL;
        }
        // 判空
        bool empty (void) const {
            return ! m_head && ! m_tail;
        }
        // 获取大小
        size_t size (void) const {
            size_t count = 0;
            for (Node* node = m_head; node;
                node = node->m_next)
                ++count;
            return count;
        }
        // 插入输出流
        friend ostream& operator<< (ostream& os,
            const List& list) {
            for (Node* node = list.m_head; node;
                node = node->m_next)
                os << *node;
            return os;
        }
    private:
        // 节点
        class Node {
        public:
            Node (const T& data = 0, Node* prev = NULL,
                Node* next = NULL) : m_data (data),
                m_prev (prev), m_next (next) {}
            friend ostream& operator<< (ostream& os,
                const Node& node) {
                return os << '(' << node.m_data << ')';
            }
            T m_data; // 数据
            Node* m_prev; // 前指针
            Node* m_next; // 后指针
        };
        bool equal (const T& a, const T& b) const {
            return a == b;
        }
        Node* m_head; // 头指针
        Node* m_tail; // 尾指针
    public:
        // 正向迭代器
        class Iterator {
        public:
            Iterator (Node* head = NULL,
                Node* tail = NULL, Node* node = NULL) :
                m_head (head), m_tail (tail),
                m_node (node) {}
            bool operator== (const Iterator& it) const {
                return m_node == it.m_node;
            }
            bool operator!= (const Iterator& it) const {
                return ! (*this == it);
            }
            Iterator& operator++ (void) {
                if (m_node)
                    m_node = m_node->m_next;
                else
                    m_node = m_head;
                return *this;
            }
            const Iterator operator++ (int) {
                Iterator old = *this;
                ++*this;
                return old;
            }
            Iterator& operator-- (void) {
                if (m_node)
                    m_node = m_node->m_prev;
                else
                    m_node = m_tail;
                return *this;
            }
            const Iterator operator-- (int) {
                Iterator old = *this;
                --*this;
                return old;
            }
            T& operator* (void) const {
                return m_node->m_data;
            }
            T* operator-> (void) const {
                return &**this;
            }
        private:
            Node* m_head;
            Node* m_tail;
            Node* m_node;
            friend class List;
        };
        Iterator begin (void) {
            return Iterator (m_head, m_tail, m_head);
        }
        Iterator end (void) {
            return Iterator (m_head, m_tail);
        }
        Iterator insert (Iterator loc, const T& data) {
            if (loc == end ()) {
                push_back (data);
                   return Iterator (m_head, m_tail,m_tail);
            }
            else {
                Node* node = new Node (data,
                    loc.m_node->m_prev, loc.m_node);
                if (node->m_prev)
                    node->m_prev->m_next = node;
                else
                    m_head = node;
                node->m_next->m_prev = node;
                return Iterator (m_head, m_tail, node);
            }
        }
        Iterator erase (Iterator loc) {
            if (loc == end ())
                throw invalid_argument ("无效迭代器!");
            if (loc.m_node->m_prev)
                loc.m_node->m_prev->m_next =
                    loc.m_node->m_next;
            else
                m_head = loc.m_node->m_next;
            if (loc.m_node->m_next)
                loc.m_node->m_next->m_prev =
                    loc.m_node->m_prev;
            else
                m_tail = loc.m_node->m_prev;
            Node* next = loc.m_node->m_next;
            delete loc.m_node;
            return Iterator (m_head, m_tail, next);
        }
    };
    // 针对const char*的特化
    template<>
    bool List<const char*>::equal (const char* const& a,
        const char* const& b) const {
        return strcmp (a, b) == 0;
    }
    // 测试用例
    int main (void) {
        try {
            List<int> list1;
            list1.push_front (20);
            list1.push_front (10);
            list1.push_back (30);
            list1.push_back (40);
            cout << list1 << endl;
            cout << list1.front () << ' ' <<
                list1.back () << endl;
            list1.pop_front ();
            list1.pop_back ();
            cout << list1 << endl;
            ++list1.front ();
            --list1.back ();
            cout << list1 << endl;
            list1.push_back (21);
            list1.push_back (25);
            list1.push_back (21);
            list1.push_back (21);
            cout << list1 << endl;
            list1.remove (21);
            cout << list1 << endl;
            List<int> list2 = list1;
            cout << list2 << endl;
            list2.back () = 100;
            cout << list2 << endl;
            cout << list1 << endl;
            list2 = list1;
            cout << list2 << endl;
            list2.front () = 100;
            cout << list2 << endl;
            cout << list1 << endl;
            cout << list1.size () << endl;
            list1.clear ();
            cout << list1 << endl;
            cout << boolalpha << list1.empty () << endl;
    //        List<string> list3;
            List<const char*> list3;
            list3.push_back ("beijing");
            list3.push_back ("tianjin");
            list3.push_front ("tianjin");
            list3.push_back ("shanghai");
            list3.push_back ("beijing");
            cout << list3 << endl;
            list3.remove (string ("beijing").c_str ());
            cout << list3 << endl;
            for (List<const char*>::Iterator it =
                list3.begin (); it != list3.end ();
                ++it)
                cout << *it << ' ';
            cout << endl;
            List<const char*>::Iterator it =
                list3.begin ();
            it++;
            it = list3.insert (it, "chongqing");
            cout << list3 << endl;
            list3.erase (it);
            cout << list3 << endl;
        }
        catch (exception& ex) {
            cout << ex.what () << endl;
            return -1;
        }
        return 0;
    }

    max.cpp

    #include <iostream>
    using namespace std;
    int max_int (int x, int y) {
        return x > y ? x : y;
    }
    string max_str (string x, string y) {
        return x > y ? x : y;
    }
    int main (void) {
        cout << "输入两个整数:" << flush;
        int nx, ny;
        cin >> nx >> ny;
        cout << "最大值:" << max_int (nx, ny) << endl;
        cout << "输入两个字符串:" << flush;
        string sx, sy;
        cin >> sx >> sy;
        cout << "最大值:" << max_str (sx, sy) << endl;
        return 0;
    }

    max2.cpp

    #include <iostream>
    #include <typeinfo>
    #include <cstring>
    using namespace std;
    // 函数模板/模板函数
    template<typename T>
    T Max (T x, T y) {
        cout << typeid (T).name () << endl;
        return x > y ? x : y;
    }
    // 模板特化
    template<>
    char* Max<char*> (char* x, char* y) {
        return strcmp (x, y) > 0 ? x : y;
    }
    template<typename T>
    void foo (void) {
        T t;
        cout << typeid (t).name () << endl;
    }
    int main (void) {
        cout << "输入两个整数:" << flush;
        int nx, ny;
        cin >> nx >> ny;
        cout << "最大值:" << Max (nx, ny) << endl;
        cout << "输入两个字符串:" << flush;
        string sx, sy;
        cin >> sx >> sy;
        cout << "最大值:" << Max (sx, sy) << endl;
        cout << "输入两个字符串:" << flush;
        char cx[256], cy[256];
        cin >> cx >> cy;
        cout << "最大值:" << Max (cx, cy) << endl;
        /*
        foo<int> ();
        foo<double> ();
        foo<string> ();
        */
        return 0;
    }

    memb1.cpp

    #include <iostream>
    using namespace std;
    template<typename T>
    class A {
    public:
        A (const T& t) : m_t (t) {}
        T m_t;
    };
    template<typename T, typename Y>
    class B {
    public:
        B (const T& t, const Y& y) :
            m_a (t), m_y (y) {}
        A<T> m_a;
        Y m_y;
    };
    int main (void) {
        B<int, string> b (100, "hello");
        cout << b.m_a.m_t << ' ' << b.m_y << endl;
        return 0;
    }

    memb2.cpp

    #include <iostream>
    using namespace std;
    template<typename T>
    class A {
    public:
        A (const T& t) : m_t (t) {}
        /*
        template<typename Y>
        void print (const Y& y) {
            cout << m_t << ' ' << y << endl;
        }
        */
        template<typename Y>
        void print (const Y& y);
        T m_t;
    };
    template<typename T>
        template<typename Y>
    void A<T>::print (const Y& y) {
        cout << m_t << ' ' << y << endl;
    }
    int main (void) {
        A<int> a (100);
        a.print<string> ("hello");
        return 0;
    }

    memb3.cpp

    #include <iostream>
    using namespace std;
    template<typename T, typename Y>
    class A {
    public:
        A (const T& t, const Y& y) :
            m_t (t), m_b (y) {}
        /*
        template<typename X>
        class B {
        public:
            B (const X& x) : m_x (x) {}
            X m_x;
        };
        */
        template<typename X> class B;
        T m_t;
        B<Y> m_b;
    };
    template<typename T, typename Y>
        template<typename X>
    class A<T, Y>::B {
    public:
        B (const X& x) : m_x (x) {}
        X m_x;
    };
    int main (void) {
        A<int, string> a (100, "hello");
        cout << a.m_t << ' ' << a.m_b.m_x << endl;
        return 0;
    }

    part.cpp

    #include <iostream>
    using namespace std;
    template<typename T1, typename T2>
    class A {
    public:
        A (void) {
            cout << "A<T1,T2>" << endl;
        }
    };
    template<typename T1>
    class A<T1, int> {
    public:
        A (void) {
            cout << "A<T1,int>" << endl;
        }
    };
    template<>
    class A<int, int> {
    public:
        A (void) {
            cout << "A<int,int>" << endl;
        }
    };
    template<typename T>
    class B {
    public:
        B (void) {
            cout << "B<T>" << endl;
        }
    };
    template<typename T>
    class B<T*> {
    public:
        B (void) {
            cout << "B<T*>" << endl;
        }
    };
    template<typename T>
    class B<T[]> {
    public:
        B (void) {
            cout << "B<T[]>" << endl;
        }
    };
    template<typename T1, typename T2, typename T3>
    class C {
    public:
        C (void) {
            cout << "C<T1,T2,T3>" << endl;
        }
    };
    template<typename T1, typename T2>
    class C<T1, T2, T2> {
    public:
        C (void) {
            cout << "C<T1,T2,T2>" << endl;
        }
    };
    template<typename T1>
    class C<T1, T1*, T1*> {
    public:
        C (void) {
            cout << "C<T1,T1*,T1*>" << endl;
        }
    };
    int main (void) {
        // 特化程度高的优先
        A<double, double> a1;
        A<double, int> a2;
        A<int, int> a3;
        // 针对指针和数组的特化优先
        B<char> b1;
        B<char*> b2;
        B<char[]> b3;
        // 匹配度高的特化优先
        C<char, short, long> c1;
        C<char, short, short> c2;
        C<char, char*, char*> c3;
        return 0;
    }

    shape.cpp

    #include <iostream>
    using namespace std;
    template<typename BASE>
    class Shape : public BASE {
    public:
        void draw (void) const {
            BASE::draw ();
        }
    };
    class Rect {
    public:
        void draw (void) const {
            cout << "绘制矩形..." << endl;
        }
    };
    class Circle {
    public:
        void draw (void) const {
            cout << "绘制圆形..." << endl;
        }
    };
    int main (void) {
        Shape<Rect> shape1;
        shape1.draw ();
        Shape<Circle> shape2;
        shape2.draw ();
        return 0;
    }

     
     
     
     
     
     
     
     
     
  • 相关阅读:
    单元测试之NUnit一
    第一个基于ArcGIS的Android应用
    NuGet的安装和使用
    PIE调用Python获得彩色直方图
    PIE调用Python返回得到直方图矩阵数组
    PIE属性表多字段的文本绘制
    微信公众号配置和使用客服消息
    python多线程爬取斗图啦数据
    微信小微商户获取申请状态
    微信小微商户申请入驻
  • 原文地址:https://www.cnblogs.com/xuxaut-558/p/10028385.html
Copyright © 2011-2022 走看看