【足迹C++primer】57、定义一个模板

定义一个模板

比较大小的函数如果v1和v2相同返回0,v1小-1,v2小1

int compare(const string &v1, const string &v2)
{
    if(v1<v2) return -1;
    if(v1>v2) return 1;
    return 0;
}

int compare(const double &v1, const double &v2)
{
    if(v1<v2) return -1;
    if(v1>v2) return 1;
    return 0;
}

使用模板

template<typename T>
int compare(const T &v1, const T &v2)
{
    if(v1<v2) return -1;
    if(v2<v1) return 1;
    return 0;
}

//范例fun1
void fun1()
{
    cout<<compare(1,0)<<endl;   //T->int
    vector<int> vec1{1,2,3}, vec2{4,5,6};   //一个接一个地比,如果第一个相同那么比第二个,否则看第一个
    cout<<compare(vec1, vec2)<<endl;    //T->vector<int>
}

模板类型参数

template<typename T>
T foo(T* p) //返回类型是T
{
    T temp=*p;
    //...
    return temp;
}

非类型模板参数

有关键字typename和class来代表template<A,B>修饰A,B类型,但是也可以不用typename和class
template<unsigned N, unsigned M>
int compare(const char (&p1)[N], const char (&p2)[M])
{
    return strcmp(p1, p2);  //比较两个字符串。设这两个字符串为str1,str2,若str1=str2,则返回零;若str1>str2,则返回正数;若str1<str2,则返回负数。
}

//inline和constexpr函数模板
template<typename T>
inline T min(const T &, const T &); //这里inline不能放到template前面

template<typename T>
int compare2(const T &v1, const T &v2)
{
    if(less<T>()(v1, v2)) return -1;
    if(less<T>()(v1, v2)) return 1;
    return 0;
}

类模板

定义类模板

template<typename T>
class Blob
{
public:
    typedef T value_type;
    //using value_type=T;
    typedef typename vector<T>::size_type size_type;
//    using size_type=typename vector<T>::size_type;
    //构造函数
    Blob();
    Blob(initializer_list<T> il);   //参数连串初始化
    //元素个数
    size_type size() const {return data->size();}   //得到vector元素个数
    bool empty() const {return data->empty();}  //判断vector是否为空

    //加减元素,拷贝
    void push_back(const T &t) {data->push_back(t);}
    //移动版本,move,&&是右值引用!!
    void push_back(T &&t) { data->push_back(std::move(t));}

    void pop_back();    //删除一个元素
    //元素调用
    T &back();  //返回最后一个元素
    T &operator[](size_type i); //下标运算符
private:
    shared_ptr<vector<T>> data;
    void check(size_type i, const string &msg) const;

};

//实现定义
template<typename T>
void Blob<T>::check(size_type i, const string &msg) const
{
    if(i >= data->size())   //如果vector的大小 不大于i的话抛出异常
        throw out_of_range(msg);
}

template<typename T>
T &Blob<T>::back()
{
    check(0, "back on empty Blob");
    return data->back();    //返回最后一个元素
}

template<typename T>    //下标运算
T & Blob<T>::operator[](size_type i)
{
    check(i, "subscript out of range"); //给出的下标是否超出范围
    return (*data)[i];
}

template<typename T>
void Blob<T>::pop_back()
{
    check(0, "pop_back on the empty Blob");
    data->pop_back();   //删除元素一个
}

//构造函数定义
template<typename T>
Blob<T>::Blob():data(make_shared<vector<T>>()) {}

template<typename T>
Blob<T>::Blob(initializer_list<T> il):data(make_shared<vector<T>>(il)){}

void fun2()
{
    //类模板实例

    Blob<int> ia;   //   Blob();
    Blob<int> ia2={0,1,2,3,4};//Blob(initializer_list<T> il)参数连串初始化
    Blob<int> squares={0,1,2,3,4,5,6,7,8,9};
    for(size_t i=0 ; i != squares.size() ; ++i)
    {
        squares[i]=i*i;
        cout<<"数值是:"<<squares[i]<<"\t";
    }
}

用模板简化代码

template<typename T>
class BlobPtr   //使用时BlobPtr<T> a,b,c;
{
public:
    BlobPtr():curr(0) {}
    BlobPtr(Blob<T> &a, size_t sz=0):wptr(a.data), curr(sz) {}  //初始化

    T &operator*() const    //一个()表示前缀
    {
        auto p=check(curr, "dereference past end");
        return (*p)[curr];  //这是*p指向vector
    }

    //前缀++,--
    BlobPtr &operator++();
    BlobPtr &operator--();

    //后置++,--
    BlobPtr &operator++(int);
    BlobPtr &operator--(int);
private:
    shared_ptr<vector<T>> check(size_t, const string &) const;
    weak_ptr<vector<T>> wptr;
    size_t curr;

};

//后缀++ --
template<typename T>
BlobPtr<T> &BlobPtr<T>::operator++(int)
{
    BlobPtr ret=*this;
    ++*this;
    return ret;
}

//后缀++ --
template<typename T>
BlobPtr<T> &BlobPtr<T>::operator--(int)
{
    BlobPtr ret=*this;
    --*this;
    return ret;
}

模板和友元

template<typename> class BlobPtr;
template<typename> class Blob2;

template<typename T>
bool operator==(const Blob<T> &, const Blob<T> &);

template<typename T>
class Blob2
{
    friend class BlobPtr<T>;
    friend bool operator==<T> (const Blob2<T> &, const Blob2<T> &);

public:
    typedef T value_type;
    //using value_type=T;
    typedef typename vector<T>::size_type size_type;
//    using size_type=typename vector<T>::size_type;
    //构造函数
    Blob2();
    Blob2(initializer_list<T> il);   //参数连串初始化
    //元素个数
    size_type size() const {return data->size();}   //得到vector元素个数
    bool empty() const {return data->empty();}  //判断vector是否为空

    //加减元素,拷贝
    void push_back(const T &t) {data->push_back(t);}
    //移动版本,move,&&是右值引用!!
    void push_back(T &&t) { data->push_back(std::move(t));}

    void pop_back();    //删除一个元素
    //元素调用
    T &back();  //返回最后一个元素
    T &operator[](size_type i); //下标运算符
private:
    shared_ptr<vector<T>> data;
    void check(size_type i, const string &msg) const;

};

通用和特殊模板的友元

template<typename T>
class Pal;

class C //普通类
{
    friend class Pal<C>;    //类
    template<typename T> friend class Pal2; //申明友元不用前向申明
};

template<typename T>
class C2
{
    friend class Pal<T>;
    template<typename X> friend class Pal2;
    friend class Pal3;
};

Befriending the template own type parameter

template<typename Type>
class Bar{friend Type;};        //这是新标准下可以这样

///模板类型别名
template<typename T>
using twin=pair<T, T>;
void fun3()
{
    twin<string> authors;
    twin<int> win_loss;
    twin<double> area;
}

静态成员

template<typename T>
class Foo
{
public:
    static size_t count() {return ctr;}
private:
    static size_t ctr;
};

template<typename T>
size_t Foo<T>::ctr=0;

void fun4()
{
    Foo<int> fi;
    auto ct=Foo<int>::count();
    ct=fi.count();      //Foo<int>::count
//    ct=Foo::count();  error:没有指定类型Foo<???>
}

主函数

int main()
{
    cout<<">>------------------------------fun1-----------------------------------<<"<<endl;
    fun1();
    cout<<">>------------------------------fun2-----------------------------------<<"<<endl;
    fun2();
    cout<<">>------------------------------fun3-----------------------------------<<"<<endl;
    fun3();

    system("pause");
    return 0;
}

马上就要把C++primer结束了,感觉还是非常好的^_^,我决定了,这个月底吧这本书完全结束!!!


【足迹C++primer】57、定义一个模板,布布扣,bubuko.com

【足迹C++primer】57、定义一个模板

上一篇:二叉树的三叉链表存储及其Java实现


下一篇:Hadoop 中利用 mapreduce 读写 mysql 数据