【足迹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、定义一个模板

时间: 2024-11-06 21:09:55

【足迹C++primer】57、定义一个模板的相关文章

【足迹C++primer】59、模板左值右值的转换

模板左值右值的转换 /** * 功能:模板左值右值的转换 * 时间:2014年7月27日08:18:06 * 作者:cutter_point */ #include<iostream> #include<algorithm> #include<utility> using namespace std; template<typename It> auto fcn(It beg, It end) -> typename remove_reference&

C++ Primer 学习笔记_75_模板与泛型编程 --模板定义

模板与泛型编程 --模板定义 引言: 所谓泛型程序就是以独立于不论什么特定类型的方式编写代码.使用泛型程序时,我们须要提供详细程序实例所操作的类型或值. 模板是泛型编程的基础.使用模板时能够无须了解模板的定义. 泛型编程与面向对象编程一样,都依赖于某种形式的多态性.面向对象编程中的多态性在执行时应用于存在继承关系的类.我们能够编写使用这些类的代码,忽略基类与派生类之间类型上的差异.仅仅要使用基类的引用或指针,基类类型或派生类类型的对象就能够使用同样的代码. 在泛型编程中,我们所编写的类和函数能够

C++ Primer 学习笔记_83_模板与泛型编程 --一个泛型句柄类

模板与泛型编程 --一个泛型句柄类 引言: [小心地雷] 这个例子体现了C++相当复杂的语言应用,理解它需要很好地理解继承和模板.在熟悉了这些特性之后再研究这个例子也许会帮助.另一方面,这个例子还能很好地测试你对这些特性的理解程度. 前面示例的Sales_item和Query两个类的使用计数的实现是相同的.这类问题非常适合于泛型编程:可以定义类模板管理指针和进行使用计数.原本不相关的Sales_item类型和 Query类型,可通过使用该模板进行公共的使用计数工作而得以简化.至于是公开还是隐藏下

【足迹C++primer】60、重载和模板

重载和模板 /** * 功能:重载和模板 * 时间:2014年7月27日16:23:32 * 作者:cutter_point */ #include<iostream> #include<algorithm> #include<sstream> using namespace std; /** 重载模板书写 */ template<typename T> string debug_rep(const T &t) { ostringstream ret

【足迹C++primer】37、关联容器概述

关联容器概述 关联容器不支持顺序容器的位置操作,如push_back或push_front 也不支持构造函数或插入操作这些接受一个元素值和一个数量值的操作. 定义关联容器 这里注意哦,我这是一个函数,里面关联容器map是包含在头文件map中的!!! 还有就是set是包含在头文件set中的,string是包含在头文件string中的!!! //关联容器初始化 void fun1() { map<string, size_t> word_count; //空容器 //列表初始化 set<st

【足迹C++primer】45、拷贝控制示例

拷贝控制示例 那么接下来尽情欣赏这个案例吧!!! /** * 功能:拷贝控制示例 * 时间:2014年7月14日10:57:39 * 作者:cutter_point */ #include<iostream> #include<set> #include<vector> #include<string> using namespace std; class Folder; /** Message类 */ class Message { friend void

【足迹C++primer】39、动态内存与智能指针(2)

动态内存与智能指针(2) 直接管理内存 void fun1() { //此new表达式在自由空间构造一个int型对象,并返回指向该对象的指针 int *pi1=new int; //pi指向一个动态分配.未初始化的无名对象 string *ps3=new string; //初始化为空string int *pi2=new int; //pi指向一个未初始化的int int *pi3=new int(1024); //pi指向的对象的值为1024 string *ps4=new string(1

C++ Primer 学习笔记_77_模板与泛型编程 --实例化

模板与泛型编程 --实例化 引言: 模板是一个蓝图,它本身不是类或函数.编译器使用模板产生指定的类或函数的特定版本号.产生模板的特定类型实例的过程称为实例化. 模板在使用时将进行实例化,类模板在引用实际模板类型时实例化,函数模板在调用它或用它对函数指针进行初始化或赋值时实例化. 1.类的实例化 当编写Queue<int>qi时,编译器自己主动创建名为Queue<int>的类.实际上,编译器通过又一次编写Queue模板,用类型int取代模板形參的每次出现而创建Queue<int

【足迹C++primer】38、关联容器操作(2)

关联容器操作(2) map的下标操作 map的下标操作 map和unordered_map容器提供了下标运算符合一个对应的at函数 对于一个map使用下标操作,其行为与数组或vector上的下标操作很不相同: 使用一个不再容器中的关键字作为下标,会添加一个此关键字的元素到map中 map和unordered_map的下标操作 c[k] 返回关键字为k的元素,如果关键字k不再c中,添加一个关键字为k的元素,对其进行值初始化 c.at(k) 访问关键字为k的元素,带参数检测,如果k不再c重那么返回一