模板内容学习杂记(一)

1.定义模板

16.1.1 函数模板

我们可以定义一个通用的函数模板,而不是为每个类型都定义一个新函数

我们可以这么做:

#include <memory>
#include <cstring>

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

    if(v1>v2)
    {
        return 1;
    }

    return 0;
}

int main()
{
    printf("%d\n",compire(1,2));
    return 0;
}

 

 

 

 

类模板

我们发现我们的模板有一个叫T的参数

//
// Created by root on 20-2-27.
//

#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
//
// Created by root on 20-2-27.
//
#include <vector>
template <typename T>class BlobA{

public:
    typedef T value_type;
    typedef typename std::vector<T>::size_type  size_type;
    BlobA()
    {

    }
    int add(T a,T b)
    {
        return a+b;
    }
};
#endif //TEST_TEMPLATE_H

调用处

#include <memory>
#include <cstring>
#include <iostream>
#include "template.h"
int main()
{
    BlobA<int> a;
    std::cout<<a.add(1,2)<<std::endl;
    return 0;
}

实例化类模板:

我们已经多次见到,当使用一个类模板的时候,我们必须要提供额外的信息是显示模板实参列表,它们被绑定到模板参数。编译器使用这些模板实参来实例话这些特定的类。

看到书这里是这么写了一个demo勾起了我的疑问

#include <memory>
#include <cstring>
#include <iostream>
#include "template.h"
int main()
{
    BlobA<int> a = {0,1,2};
    std::cout<<a.add(1,2)<<std::endl;
    return 0;
}

为什么类可以被初始化为{0,1,2}

原来构造函数里重载在这里

//
// Created by root on 20-2-27.
//

#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
//
// Created by root on 20-2-27.
//
#include <vector>
template <typename T>class BlobA{

public:
    typedef T value_type;
    typedef typename std::vector<T>::size_type  size_type;
    BlobA()
    {

    }
    BlobA(std::initializer_list<T> il)
    {

    }
    int add(T a,T b)
    {
        return a+b;
    }
};
#endif //TEST_TEMPLATE_H

这里简单说一下自定义类型使用initializer_list

c++11也提供了方法,让用户可以在自定义类型(一般指类)中使用初始化列表。

我们看一下实例化后的类

BlobA(std::initializer_list il)
{

    for (auto a : il)
    {
        std::cout<<a<<std::endl;
    }
}

结果是0,1,2,3

我们继续看书后面的内容

智能指针使用模板

std::shared_ptr<BlobA<int>> data;

data是一个shared_ptr的实例,此shared_ptr保存了一个类型为T的对象的vector实例

1.定义模板

16.1.1 函数模板

我们可以定义一个通用的函数模板,而不是为每个类型都定义一个新函数

我们可以这么做:

#include <memory>
#include <cstring>

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

    if(v1>v2)
    {
        return 1;
    }

    return 0;
}

int main()
{
    printf("%d\n",compire(1,2));
    return 0;
}

类模板

我们发现我们的模板有一个叫T的参数

//
// Created by root on 20-2-27.
//

#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
//
// Created by root on 20-2-27.
//
#include <vector>
template <typename T>class BlobA{

public:
    typedef T value_type;
    typedef typename std::vector<T>::size_type  size_type;
    BlobA()
    {

    }
    int add(T a,T b)
    {
        return a+b;
    }
};
#endif //TEST_TEMPLATE_H

调用处

#include <memory>
#include <cstring>
#include <iostream>
#include "template.h"
int main()
{
    BlobA<int> a;
    std::cout<<a.add(1,2)<<std::endl;
    return 0;
}

实例化类模板:

我们已经多次见到,当使用一个类模板的时候,我们必须要提供额外的信息是显示模板实参列表,它们被绑定到模板参数。编译器使用这些模板实参来实例话这些特定的类。

看到书这里是这么写了一个demo勾起了我的疑问

#include <memory>
#include <cstring>
#include <iostream>
#include "template.h"
int main()
{
    BlobA<int> a = {0,1,2};
    std::cout<<a.add(1,2)<<std::endl;
    return 0;
}

为什么类可以被初始化为{0,1,2}

原来构造函数里重载在这里

//
// Created by root on 20-2-27.
//

#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
//
// Created by root on 20-2-27.
//
#include <vector>
template <typename T>class BlobA{

public:
    typedef T value_type;
    typedef typename std::vector<T>::size_type  size_type;
    BlobA()
    {

    }
    BlobA(std::initializer_list<T> il)
    {

    }
    int add(T a,T b)
    {
        return a+b;
    }
};
#endif //TEST_TEMPLATE_H

这里简单说一下自定义类型使用initializer_list

c++11也提供了方法,让用户可以在自定义类型(一般指类)中使用初始化列表。

我们看一下实例化后的类

BlobA(std::initializer_list il)
{

    for (auto a : il)
    {
        std::cout<<a<<std::endl;
    }
}

结果是0,1,2,3

我们继续看书后面的内容

智能指针使用模板

std::shared_ptr<BlobA<int>> data;

data是一个shared_ptr的实例,此shared_ptr保存了一个类型为T的对象的vector实例

类模板的成员函数

我们既可以在类模板内部也可以在类模板外部为其定义成员函数,且定义在模板内部的成员函数被隐式声明为内敛函数。

定义在模板外的类模板成员函数必须以template开始

与往常一样当我们在类外定义一个成员函数的时候,必须说明成员属于哪一个类。而且一个模板生成类的名字中必须包含其模板实参。当我们定义一个成员函数的时候,必须说明成员属于哪个类。而且从一个模板生成类的名字中必须包含模板的实参。当我们定义一个成员函数的时候,模板实参与模板形参相同。对于一个成员函数,对应blob的成员应该是这个样子的。

template <typename T>
ret-type Blob<T>::member-name(parm-list)

注意模板的定义和声明不能分开为两个文件,因为在编译的时候并不会生成具体类,只有在调用的时候会,所以需要包含.cc,但是这并不是一个好方案,所以还是写在一个.h文件中比较好

比如一个放在.h中 一个放在.cc中

类模板与另一个模板间的友好关系最常见的形式是建立实例以及友元间的友好关系

//
// Created by root on 20-2-27.
//

#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
#include <vector>
#include <iostream>
// Created by root on 20-2-27.
//

template <typename >class BlobPtr;
template <typename >class Blob;

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

public:
    friend class BlobPtr<T>;
    friend bool operator == <T>(const Blob<T>&,const Blob<T>&);
    typedef T value_type;
    typedef typename std::vector<T>::size_type  size_type;
    BlobA()
    {

    }
    BlobA(std::initializer_list<T> il)
    {

        for (auto a : il)
        {
            std::cout<<a<<std::endl;
        }
    }
    int add(T a,T b);

};

template <typename T>
int BlobA<T>::add(T a, T b) {
    return a+b;
}
#endif //TEST_TEMPLATE_H

模板类型别名

模板类型的特性,typedef BlobA data2;

另一种方式

希望指定别名的不是一个实例化的模板类,而是一个模板

template <typename T>using partNo = BlobA<unsigned>;

类模板的static成员

与其他任何类都相同,类模板也可以声明static成员。

template <typename T>class BlobA{
public:

    static std::size_t count(){ return ctr;};

    static std::size_t ctr;

private:
};

//初始化
template <typename T>size_t BlobA<T>::ctr = 0;

//使用
int main()
{

    std::cout<<partNo<int>::count()<<std::endl;
    return 0;
}

 

 

类模板的成员函数

我们既可以在类模板内部也可以在类模板外部为其定义成员函数,且定义在模板内部的成员函数被隐式声明为内敛函数。

定义在模板外的类模板成员函数必须以template开始

与往常一样当我们在类外定义一个成员函数的时候,必须说明成员属于哪一个类。而且一个模板生成类的名字中必须包含其模板实参。当我们定义一个成员函数的时候,必须说明成员属于哪个类。而且从一个模板生成类的名字中必须包含模板的实参。当我们定义一个成员函数的时候,模板实参与模板形参相同。对于一个成员函数,对应blob的成员应该是这个样子的。

template <typename T>
ret-type Blob<T>::member-name(parm-list)

注意模板的定义和声明不能分开为两个文件,因为在编译的时候并不会生成具体类,只有在调用的时候会,所以需要包含.cc,但是这并不是一个好方案,所以还是写在一个.h文件中比较好

比如一个放在.h中 一个放在.cc中

类模板与另一个模板间的友好关系最常见的形式是建立实例以及友元间的友好关系

//
// Created by root on 20-2-27.
//

#ifndef TEST_TEMPLATE_H
#define TEST_TEMPLATE_H
#include <vector>
#include <iostream>
// Created by root on 20-2-27.
//

template <typename >class BlobPtr;
template <typename >class Blob;

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

public:
    friend class BlobPtr<T>;
    friend bool operator == <T>(const Blob<T>&,const Blob<T>&);
    typedef T value_type;
    typedef typename std::vector<T>::size_type  size_type;
    BlobA()
    {

    }
    BlobA(std::initializer_list<T> il)
    {

        for (auto a : il)
        {
            std::cout<<a<<std::endl;
        }
    }
    int add(T a,T b);

};

template <typename T>
int BlobA<T>::add(T a, T b) {
    return a+b;
}
#endif //TEST_TEMPLATE_H

模板类型别名

模板类型的特性,typedef BlobA data2;

另一种方式

希望指定别名的不是一个实例化的模板类,而是一个模板

template <typename T>using partNo = BlobA<unsigned>;

类模板的static成员

与其他任何类都相同,类模板也可以声明static成员。

template <typename T>class BlobA{
public:

    static std::size_t count(){ return ctr;};

    static std::size_t ctr;

private:
};

//初始化
template <typename T>size_t BlobA<T>::ctr = 0;

//使用
int main()
{

    std::cout<<partNo<int>::count()<<std::endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章