6.4-数据结构&算法-模板/函数模板/类模板/特化

Posted xuxaut-558

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

 


 
 
 
 
 
 
 
 
 

以上是关于6.4-数据结构&算法-模板/函数模板/类模板/特化的主要内容,如果未能解决你的问题,请参考以下文章

C++模板初阶

函数模板&类模板

C++ 提高教程 函数模板-函数模板案列

C++ 提高教程 模板-函数模板和类模板

模板-template

模板-template