zoukankan      html  css  js  c++  java
  • 16 模板与泛型编程 | 定义模板

     Blob类

     1 #include<iostream>
     2 #include<initializer_list>
     3 #include<vector>
     4 using namespace std;
     5 
     6 template <typename T> 
     7 class Blob {
     8 public:
     9     typedef typename vector<T>::size_type size_type;
    10 
    11     Blob();
    12     Blob(initializer_list<T> il);
    13     size_type size() const { return data->size(); }
    14     bool empty() const { return data->empty(); }
    15     void push_back(const T &t) { data->push_back(t); }
    16     void push_back(T &&t) { data->push_back(std::move(t)); }
    17     void pop_back();
    18     T& back();
    19     T& operator[](size_type i);
    20 
    21 private:
    22     shared_ptr<vector<T>> data;
    23     void check(size_type i, const string &msg) const;
    24 };
    25 
    26 template <typename T>
    27 void Blob<T>::check(size_type i, const string &msg) const
    28 {
    29     if (i >= data->szie())
    30         throw out_of_range(msg);
    31 }
    32 
    33 template <typename T>
    34 Blob<T>::Blob() : data(make_shared<vector<T>>()) {}
    35 
    36 template <typename T>
    37 Blob<T>::Blob(initializer_list<T> il) : data(make_shared<vector<T>>(il)) {}
    38 
    39 template <typename T>
    40 T& Blob<T>::back()
    41 {
    42     check(0, "back on empty Blob");
    43     return data->back();
    44 }
    45 
    46 template <typename T>
    47 T& Blob<T>::operator[](size_type i)
    48 {
    49     check(i, "subscript out of range");
    50     return (*data)[i];
    51 }
    52 
    53 template <typename T>
    54 void Blob<T>::pop_back()
    55 {
    56     check(0, "pop_back on emppty Blob");
    57     data->pop_back();
    58 }
    View Code

    BlobPtr类

    头文件

      1 /********BlobPtr*********/
      2 
      3 #ifndef BLOBPTR_H
      4 #define BlOBPTR_H
      5 #include<iostream>
      6 #include<initializer_list>
      7 #include<string>
      8 #include<memory>
      9 #include<vector>
     10 using namespace std;
     11 
     12 template <typename> class BlobPtr;  //前置声明, 在Blob申明友元所需要的
     13 template <typename> class Blob;     //前置申明,运算符==中的参数所需要的
     14 template <typename T>
     15 bool operator==(const Blob<T>&, const Blob<T>&);
     16 
     17 template <typename T>
     18 class Blob {
     19     friend class BlobPtr<T>;
     20     friend bool operator ==<T>(const Blob<T>&, const Blob<T>&);
     21 public:
     22     typedef typename vector<T>::size_type size_type;
     23 
     24     Blob();
     25     Blob(initializer_list<T> il);
     26     size_type size() const { return data->size(); }
     27     bool empty() const { return data->empty(); }
     28     void push_back(const T &t) { data->push_back(t); }
     29     void push_back(T &&t) { data->push_back(std::move(t)); }
     30     void pop_back();
     31     T& back();
     32     T& operator[](size_type i);
     33 
     34     BlobPtr<T> begin() { return BlobPtr<T>(*this); }
     35     BlobPtr<T> end()
     36     {
     37         auto ret = BlobPtr<T>(*this, data->size());
     38         return ret;
     39     }
     40 private:
     41     shared_ptr<vector<T>> data;
     42     void check(size_type i, const string &msg) const;
     43 };
     44 
     45 template <typename T>
     46 void Blob<T>::check(size_type i, const string &msg) const
     47 {
     48     if (i >= data->szie())
     49         throw out_of_range(msg);
     50 }
     51 
     52 template <typename T>
     53 Blob<T>::Blob() : data(make_shared<vector<T>>()) {}
     54 
     55 template <typename T>
     56 Blob<T>::Blob(initializer_list<T> il) : data(make_shared<vector<T>>(il)) {}
     57 
     58 template <typename T>
     59 T& Blob<T>::back()
     60 {
     61     check(0, "back on empty Blob");
     62     return data->back();
     63 }
     64 
     65 template <typename T>
     66 T& Blob<T>::operator[](size_type i)
     67 {
     68     check(i, "subscript out of range");
     69     return (*data)[i];
     70 }
     71 
     72 template <typename T>
     73 void Blob<T>::pop_back()
     74 {
     75     check(0, "pop_back on emppty Blob");
     76     data->pop_back();
     77 }
     78 
     79 template <typename T>
     80 bool operator==(const Blob<T> &lhs, const Blob<T> &rhs)
     81 {
     82     if (rhs.size() != lhs.size())
     83         return false;
     84     for (size_t i = 0; i != lhs.size(); +i)
     85         if (lhs[i] != rhs[i])
     86             return false;
     87     return true;
     88 }
     89 
     90 /******************************************************************/
     91 
     92 template <typename T>
     93 bool operator==(const BlobPtr<T>&, const BlobPtr<T>&);
     94 
     95 template <typename T>
     96 class BlobPtr {
     97     friend bool operator==<T>(const BlobPtr<T>&, const BlobPtr<T>&);
     98 public:
     99     BlobPtr() : curr(0) {}
    100     BlobPtr(Blob<T> &a, size_t sz = 0) : wptr(a.data), curr(sz) {}
    101     
    102     T& operator*() const;
    103 
    104     BlobPtr& operator++();       //前置运算符
    105     BlobPtr& operator--();       //前置运算符
    106     BlobPtr operator++(int);     //后置运算符
    107     BlobPtr operator--(int);     //后置运算符
    108 private:
    109     shared_ptr<vector<T>> check(size_t, const string &) const;
    110     weak_ptr<vector<T>> wptr;
    111     size_t curr;  //数组当前的位置
    112 };
    113 
    114 template <typename T>
    115 shared_ptr<vector<T>> BlobPtr<T>::check(size_t i, const string &msg) const
    116 {
    117     auto ret = wptr.lock();
    118     if (!ret)
    119         throw std::runtime_error("unbound BlobPtr");
    120     if (i >= ret->size())
    121         throw std::out_of_range(msg);
    122     return ret;
    123 }
    124 
    125 template <typename T>
    126 T& BlobPtr<T>::operator*() const
    127 {
    128     auto p = check(curr, "dereference past end");
    129     return (*p)[curr];
    130 }
    131 
    132 template <typename T>
    133 BlobPtr<T> BlobPtr<T>::operator++(int) //++后置运算符
    134 {
    135     BlobPtr ret = *this;
    136     ++*this;
    137     return ret;
    138 }
    139 
    140 template <typename T>
    141 BlobPtr<T> BlobPtr<T>::operator--(int) //--后置运算符
    142 {
    143     BlobPtr ret = *this;
    144     --*this;
    145     return ret;
    146 }
    147 
    148 template <typename T>
    149 BlobPtr<T>& BlobPtr<T>::operator++() //++前置运算符
    150 {
    151     check(curr, "increment past end of BlobPtr");
    152     ++curr;
    153     return *this;
    154 }
    155 
    156 template <typename T>
    157 BlobPtr<T>& BlobPtr<T>::operator--() //--前置运算符
    158 {
    159     --curr;  //如果是0,则继续递减它产生一个无效下标
    160     check(curr, "decrement past begin of BlobPtr");
    161     return *this;
    162 }
    163 
    164 template <typename T>
    165 bool operator == (const BlobPtr<T> &lhs, const BlobPtr<T> &rhs)
    166 {
    167     return (lhs.wptr.lock().get() == rhs.wptr.lock().get()) && lhs.curr == rhs.curr;
    168 }
    169 
    170 template <typename T>
    171 bool operator!=(const BlobPtr<T> &lhs, const BlobPtr<T> &rhs)
    172 {
    173     return !(rhs == lhs);
    174 }
    175 #endif
    View Code

    主函数

     1 #include<iostream>
     2 #include<string>
     3 #include"BlobPtr.h"
     4 using namespace std;
     5 
     6 int main()
     7 {
     8     Blob<string> b1;
     9     cout << b1.size() << endl;
    10     {
    11         Blob<string> b2 = { "a", "an", "the" };
    12         b1 = b2;
    13         b2.push_back("about");
    14         cout << b1.size() << " " << b2.size() << endl;
    15     }
    16     cout << b1.size() << endl;
    17     for (auto p = b1.begin(); p != b1.end(); ++p)
    18         cout << *p << " ";
    19     return 0;
    20 }
    View Code

    输出结果:

    成员模板 

    1. 若外围类定义也是类模板,则在类体外定义成员模板时,它接收二个模板形参集:一个是外围类的,另一个是自身的:

     1 template<typename T1>
     2 struct string 
     3 {
     4     // 成员模板函数
     5     template<typename T2>
     6     int compare(const T2&);
     7 
     8     // 构造函数亦可为模板
     9     template<typename T2>
    10     string(const std::basic_string<T2>& s) { /*...*/ }
    11 };
    12 
    13 // string<T1>::compare<T2> 的类外定义 
    14 template<typename T1> // 对于外围类模板
    15 template<typename T2> // 对于成员模板
    16 int string<T1>::compare(const T2& s) { /* ... */

    2. 可以声明拥有相同名称的非模板成员函数和模板成员函数。在冲突的情况下(某些模板特化准确匹配非模板函数的签名),该名称的使用及类型指代非模板成员,除非提供显式模板实参列表。 

     1 #include<iostream>
     2 using namespace std;
     3 
     4 template<typename T>
     5 struct A 
     6 {
     7     void f(int); // 非模板成员
     8 
     9     template<typename T2>
    10     void f(T2); // 成员模板    
    11 };
    12 
    13 template <typename T>
    14 void A<T>::f(int)
    15 {
    16     cout << "非模板成员" << endl;
    17 }
    18 
    19 // 模板成员定义
    20 template <typename T>
    21 template <typename T2>
    22 void A<T>::f(T2)
    23 {
    24     cout << "成员模板" << endl;
    25 }
    26 
    27 int main()
    28 {
    29     A<char> ac;
    30     ac.f('c'); // 调用模板函数 A<char>::f<char>(int)
    31     ac.f(1);   // 调用非模板函数 A<char>::f(int)
    32     ac.f<>(1); // 调用模板函数 A<char>::f<int>(int)
    33     return 0;
    34 }

    运行结果:

    3. 举例

     1 #include <iostream>
     2 #include <vector>
     3 #include <algorithm>
     4 using namespace std;
     5 
     6 struct Printer 
     7 { 
     8     ostream& os;
     9     Printer(ostream& os): os(os) {}
    10 
    11     template<typename T>
    12     void operator()(const T& obj) { os << obj << ' '; } // 成员模板
    13 };
    14 
    15 int main()
    16 {
    17     vector<int> v = { 1,2,3 };
    18     for_each(v.begin(), v.end(), Printer(cout));
    19     string s = "abc";
    20     for_each(s.begin(), s.end(), Printer(cout));
    21 }

    运行结果:

    for_each源码:

    1 template<typename InputIterator, typename Function>
    2 Function for_each(InputIterator beg, InputIterator end, Function f) 
    3 {
    4   while(beg != end) 
    5     f(*beg++);
    6 }
    View Code

    模板实参推断

  • 相关阅读:
    gulp之webpack-stream模块
    AMD、CMD与commonJS
    gulp之gulp-replace模块
    gulp之gulp-uglify模块
    gulp之gulp-sequence模块
    规范-命名、词汇
    gulp之gulp-connect模块
    angularjs $injector:nomod
    because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled
    jxls2 java.lang.NegativeArraySizeException
  • 原文地址:https://www.cnblogs.com/sunbines/p/9367879.html
Copyright © 2011-2022 走看看