C++:模板

模板

模板(template)是一个类或者一个函数,以一组类型或/和整数为参数:

template<typename T>
class vector{
public:
    //...
    int size() const;
private:
    int sz;
    T* p;
};
template <class T>
int vector<T>::size() const
{
    return sz;
}

在模板参数列表中,class表示类型,也可以用typename来表示类型。模板类的成员函数隐含地定义为模板函数,其模板参数与模板类一致。
整数模板参数必须是常量表达式

template <typename T, int sz>
class Fixed_array{
public:
    T a[sz];
    //...
    int size() const {return sz;};
};

Fixed_array<char, 256> x1;      //正确的定义
int var = 256;
Fixed_array<char, var> x2;      //错误的定义:非const模板实参

模板参数

当使用模板类时,需要指定模板参数:

vector<int> v1;         //正确
vector v2;              //错误,模板实参缺失
vector<int, 2> v3;      //错误,模板实参过多
vector<2> v4;           //错误,要求模板实参为类型

模板函数的模板参数则通常通过函数的实参推断出来:

template<class T>
T find(vector<T>& v,int i)
{
    return v[i];
}
vector<int> v1;
vector<double> v2;
//...
int x1 = find(v1,2);        //find()的T为int
double x2 = find(v2,2);     //find()的T为double

模板实例化

指明了一组特定模板参数的模板版本称为特例(specialization)
由模板和一组参数生成的特例的过程称为模板实例化(template instantition)
通常是由编译器从一个模板和一组模板参数生成一个特例,但程序员也可以定义特殊的特例,这通常是因为一般模板不适合一组特殊的模板参数,eg:

template<class T> struct Compare{       //通用比较
    bool operator()(const T&a, const T&b)const
    {
        return a<b;
    }
};

template<> struct Compare<const char*>{         //比较C风格的字符串
    bool operator()(const char* a,const char* b) const
    {
        return strcmp(a,b) == 0;
    }
};

Compare<int> c1;                //通用风格
Compare<const char*>c2;         //C风格字符串比较
boo1 b1 = c1(1,2);              //使用通用比较
bool v=b2 = c2("asd","dfg");    //使用C风格字符串比较

对于函数,通过重载可以达到大致类似的效果:

template<class T>bool compare(const T&a,const T&b)
{
    return a<b;
}
bool compare(cosnt char* a,const char* b)       //比较C风格的字符串
{
    return strcmp(a,b) == 0;
}
boo1 b3 = compare(2,3);                         //使用通用比较
bool b4 = compare("asd","fgh");                 //使用C风格字符串比较    

模板的分离编译(即,头文件中只有声明,而唯一的定义置于.cpp文件中)不具备可移植性,因此,如果模板需要在多个.cpp文件中使用的话,应该将其完整定义置于头文件中。

模板成员类型

模板的成员可以是类型,也可以不是类型(例如数据成员和成员函数)。
这意味着,一般很难分辨一个成员名是类型还是非类型。处于语言技术上的原因,编译器必须要知道这方面的信息,因此有时我们必须将相关的信息告知编译器。
为此,我们需要使用关键字typename
eg

template<class T> struct Vec{
    typedef T value_type;    //一个成员类型
    static int const;        //一个数据类型
    //...
};

template<class T> void my_fct(Vec<T>& v)
{
    int x = Vec<T>::count;     //默认情况下,编译器假定成员名引用的是非类型成员
    v.count = 7;               //引用非类型成员的更简单的办法
    typename Vec<T>::value_type xx = x;   //这里需要typename
    //..
}

猜你喜欢

转载自blog.csdn.net/lym940928/article/details/80065182