C++ 模板的定义、使用及特化

13 篇文章 0 订阅

1、模板函数

模板函数的定义格式:

template  <class 形参名1class 形参名2...class 形参名3> 
//这里class也可以换为typename
返回值类型 函数名()
{...}
template <class T>
bool Isequal(T &a, T &b)
{
    return a == b;
}
int main()
{
    string s1("hello");
    string s2 = s1;
    cout<<Isequal(1, 2)<<endl;
    cout << Isequal(s1, s2) << endl;
    cout << Isequal<int>(1, 1.2) << endl;  //模板参数的显示实例化 结果为1
    cout << Isequal<double>(1, 1.2) << endl;  //模板参数的显示实例化,结果为0
    system("pause");
    return 0;
}

2.模板类

什么是类模板?
一个类模板(也称为类属类或类生成类)允许用户为类定义一种模式,使得类中的某些数据成员、默写成员函数的参数、某些成员函数的返回值,能够取任意类型(包括系统预定义的和用户自定义的)。
如果一个类中数据成员的数据类型不能确定,或者是某个成员函数的参数或返回值的类型不能确定,就必须将此类声明为模板,它的存在不是代表一个具体的、实际的类,而是代表着一类类。类模板中的成员函数全部都是模板函数(该说法正确)。

什么是模板类?
模板类是类模板实例化后的一个产物。可以从类模板派生出新的类,既可以派生类模板,也可以派生非模板类。

模板类的定义格式

template <class 形参名1class 形参名2...,class 形参名n>
class 类名
{...}

下面以容器适配器为例进行分析:

template <typename T> 
class SeqList 
{ 
private:    
    int _size;    
    int _capacity;    
    T* _data;
};

template <class T ,class Container=SeqList<int>>//Container就是一个模板形参,模板实参传什么类型,Container就是什么类型
class Stack
{
public:
    void push(const T &x);
    void pop();
    const T& top();
    bool empty();
protected:
    Container _con;
};

int main()
{
    Stack<int> s1;  
    Stack<int, SeqList< int>> s2;
    system("pause");
    return 0;
}

3.模板的模板类

template <typename T> 
class SeqList 
{ 
private:    
    int _size;    
    int _capacity;    
    T* _data;
};
template <class T ,template <class>  class Container=SeqList>//缺省参数,这里template <class>表示Container是一个模板类型的模板形参
class Stack
{
public:
    void push(const T &x);
    void pop();
    const T& top();
    bool empty();
protected:
    Container<T> _con;
};

4.模板类的特化

C++中的模板特化不同于模板的实例化,模板参数在某种特定类型下的具体实现称为模板的特化。模板特化有时也称之为模板的具体化。模板的全特化和偏特化都是在已经定义的模板类之上,不能单独存在。

特化整体上分为全特化和偏特化

  • 全特化:模板中的模板参数全部被指定为特定的类型,全特化也就是定义了一个全新的类型。完全产生确定的东西,不需要在编译期间搜寻合适的特化实现。
  • 偏特化:模板中的模板参数没有被全部确定,需要在编译的时候进行确定
    模板函数只可以进行全特化,而模板类既可以进行全特化,也可以进行偏特化

根据特化的对象可分为
(1)函数模板特化:当函数中需要对某些类型进行特化处理时,称为函数模板的特化

类模板的特化实例:

//  模版特化
template <class T>
int compare(const T left, const T right){
    std::cout <<"in template<class T>..." <<std::endl;
    return (left - right);
}


//  这个是一个特化的函数模版
template < >
int compare<const char*>(const char* left, const char* right){
    std::cout <<"in special template< >..." <<std::endl;
    return strcmp(left, right);
}

//  特化的函数模版, 两个特化的模版本质相同, 因此编译器会报错
//  这种写法也可以??
// error: redefinition of 'int compare(T, T) [with T = const char*]'|
//template < >
//int compare(const char* left, const char* right)
//{
//    std::cout <<"in special template< >..." <<std::endl;
//
//    return strcmp(left, right);
//}


//  这个其实本质是函数重载
int compare(char* left, char* right){
    std::cout <<"in overload function..." <<std::endl;

    return strcmp(left, right);
}

int main( ){
    compare(1, 4);

    const char *left = "hello";
    const char *right = "world";
    compare(left, right);

    return 0;
}

当函数调用 有特化函数时,会优先调用特化的匹配函数,而不是通过函数模板进行实例化。

(2)类模板的特化:当类中需要对某些类型进行特化处理时,称为类模板的特化

模板参数的类模板特化有如下三种情况:

  • 特化为绝对类型
  • 特化为引用、指针类型
  • 特化为另外一个模板

下面分别就这三种情况进行说明:
特化为绝对类型:

#include <iostream>
#include <cstring>
#include <cmath>
// general version
template<class T>
class Compare
{
public:
    static bool IsEqual(const T& lh, const T& rh)
    {
        std::cout <<"in the general class..." <<std::endl;
        return lh == rh;
    }
};
// specialize for float
template<>
class Compare<float>
{
public:
    static bool IsEqual(const float& lh, const float& rh)
    {
        std::cout <<"in the float special class..." <<std::endl;

        return std::abs(lh - rh) < 10e-3;
    }
};

// specialize for double
template<>
class Compare<double>
{
public:
    static bool IsEqual(const double& lh, const double& rh)
    {
        std::cout <<"in the double special class..." <<std::endl;

        return std::abs(lh - rh) < 10e-6;
    }
};


int main(void)
{
    Compare<int> comp1;
    std::cout <<comp1.IsEqual(3, 4) <<std::endl;
    std::cout <<comp1.IsEqual(3, 3) <<std::endl;

    Compare<float> comp2;
    std::cout <<comp2.IsEqual(3.14, 4.14) <<std::endl;
    std::cout <<comp2.IsEqual(3, 3) <<std::endl;

    Compare<double> comp3;
    std::cout <<comp3.IsEqual(3.14159, 4.14159) <<std::endl;
    std::cout <<comp3.IsEqual(3.14159, 3.14159) <<std::endl;
    return 0;
}

特化为引用指针类型:

template <class _Iterator>
struct iterator_traits {
  typedef typename _Iterator::iterator_category iterator_category;
  typedef typename _Iterator::value_type        value_type;
  typedef typename _Iterator::difference_type   difference_type;
  typedef typename _Iterator::pointer           pointer;
  typedef typename _Iterator::reference         reference;
};

// specialize for _Tp*
template <class _Tp>
struct iterator_traits<_Tp*> {
  typedef random_access_iterator_tag iterator_category;
  typedef _Tp                         value_type;
  typedef ptrdiff_t                   difference_type;
  typedef _Tp*                        pointer;
  typedef _Tp&                        reference;
};

// specialize for const _Tp*
template <class _Tp>
struct iterator_traits<const _Tp*> {
  typedef random_access_iterator_tag iterator_category;
  typedef _Tp                         value_type;
  typedef ptrdiff_t                   difference_type;
  typedef const _Tp*                  pointer;
  typedef const _Tp&                  reference;
};

特化为另一个模板类:

// specialize for vector<T>
template<class T>
class Compare<vector<T> >
{
public:
    static bool IsEqual(const vector<T>& lh, const vector<T>& rh){
        if(lh.size() != rh.size()) return false;
        else{
            for(int i = 0; i < lh.size(); ++i){
                if(lh[i] != rh[i]) return false;
            }
        }
        return true;
    }
};

把IsEqual()的参数类型定义为vector类型,这种类型叫做偏特化类型,可以把这种偏特化类型自定义为我们的模板类类型:

// specialize for any template class type
template <class T1> 
struct SpecializedType
{
    T1 x1;
    T1 x2;
};
template <class T>
class Compare<SpecializedType<T> >
{
public:
    static bool IsEqual(const SpecializedType<T>& lh, const SpecializedType<T>& rh)
    {
        return Compare<T>::IsEqual(lh.x1 + lh.x2, rh.x1 + rh.x2);
    }
};

5.模板不支持分离编译

模板是不支持分离编译的,如下是之前总结的模板为什么不支持分离编译
https://blog.csdn.net/wyn126/article/details/76733943

6.模板总结:

优点:

  • 模板复用了代码,节省资源,C++标准库因此而产生
  • 增强了代码的灵活性

缺点:

  • 模板让代码变得凌乱复杂,不易维护,增加了编译时间
  • 出现模板编译错误时,错误信息非常凌乱,不易维护
  • 每种类型的参数都会产生额外的代码,导致文件膨胀,代码量过长

原文链接:https://blog.csdn.net/wyn126/article/details/79847665

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值