【C++初阶】模板进阶

【C++初阶】模板进阶

🥕个人主页:开敲🍉

🔥所属专栏:C++🥭

🌼文章目录🌼

1. 非类型模板参数

2. 模板的特化

    2.1 特化的概念

    2.2 函数模板特化

    2.3 类模板特化

        2.3.1 全特化

        2.3.2 偏特化

3. 模板分离编译

    3.1 什么是分离编译

    3.2 模板的分离编译

    3.3 解决方法

4. 模板总结

1. 非类型模板参数

  模板参数分为类型参数非类型参数

  类型参数:出现在模板参数列表中,跟在class或者typename之类的参数类型名称后。

  非类型参数:使用一个常量作为模板的参数,在类模板中将该参数视为常量使用。

#define _CRT_SECURE_NO_WARNINGS 1


#include <iostream>
#include <assert.h>
using namespace std;

namespace gjk
{

//N就是非类型模板参数,用于定义数组的长度
    template<class T, size_t N = 10>
    class array
    {
    public:
        array()
        {
            _size = 0;
        }

        void push_back(const T& data)
        {
            _array[_size++] = data;
        }

        size_t size()
        {
            return _size;
        }
        T& operator[](size_t index)
        {
            return _array[index];
        }

        const T& operator[](size_t index) const
        {
            return _array[index];
        }

        bool empty()
        {
            return _size == 0;
        }
    private:
        T _array[N];
        size_t _size;
    };
}


int main()
{
    gjk::array<int> a1;

    a1.push_back(1);
    a1.push_back(2);
    a1.push_back(3);
    a1.push_back(4);
    a1.push_back(5);

    cout << a1[0] << endl;
    cout << a1[1] << endl;
    cout << a1[2] << endl;
    cout << a1[3] << endl;
    cout << a1[4] << endl;

    return 0;
}

注意:

  ① 浮点数、类对象以及字符串不允许作为非类型模板参数

  ② 非类型的模板参数必须在编译时就能确定

2. 模板的特化
    2.1 特化的概念

  通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些
错误的结果,需要特殊处理,比如:实现了一个专门用来进行小于比较的函数模板:

  这里我们Max函数是比较left和rihgt的值,判断left的值是否大于right的值。第一个Max(1,2)就是比较值的大小。而下面的Max(x,y)则是比较的x和y的地址大小,这显然是不符合我们的要求的。这时候我们就可以使用特化,让x和y也能够比较值的大小。

    2.2 函数模板特化

  函数模板的特化步骤:

必须要有一个基础的函数模板,也就是必须要有一个特化的对象。

关键字template后接一对空的<>

函数名后跟一对<>,里面是需要特化的类型

函数形参列表:函数形参列表必须要和函数模板一样

    2.3 类模板特化
        2.3.1 全特化

  全特化即是将模板参数列表中所有的参数都确定化。

        2.3.2 偏特化

  偏特化:任何针对模版参数进一步进行条件限制设计的特化版本。比如对于以下模板类:

template<class T1,class T2>
class Max
{
public:
    void Printf()
    {
        cout << "<T,T>" << endl;
    }

private:
    T1 _a;
    T2 _b;
};

//偏特化char,只要传的第二个参数为char,不管第一个是什么类型,都进这个类

template<class T>
class Max<T, char>
{
public:
    void Printf()
    {
        cout << "<T,char>" << endl;
    }

private:
    int _a;
    char _b;
};

//偏特化int,只要传的第一个参数是int,不管第二个是什么类型,都走这个类
template<class T>
class Max<int, T>
{
public:
    void Printf()
    {
        cout << "<int,T>" << endl;
    }

private:
    int _a;
    char _b;
};

//篇特化double,只要传的第二个参数是double,不管第一个是什么类型都走这个
template<class T>
class Max<T, double>
{
public:
    void Printf()
    {
        cout << "<T,double>" << endl;
    }

private:
    int _a;
    char _b;
};

3. 模板分离编译
    3.1 什么是分离编译

  一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有
目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。

    3.2 模板的分离编译

  假如有以下场景,模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义:

// a.h
template<class T>
T Add(const T& left, const T& right);


// a.cpp
template<class T>
T Add(const T& left, const T& right)
{
    return left + right;
}

// main.cpp
#include"a.h"
int main()
{
    Add(1, 2);
    Add(1.0, 2.0);
    return 0;
}

    3.3 解决方法

   将声明和定义放到一个文件 "xxx.hpp" 里面或者xxx.h其实也是可以的。推荐使用这种。

   模板定义的位置显式实例化。这种方法不实用,不推荐使用。

4. 模板总结

优点:

   模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生。

   增强了代码的灵活性。

缺点:

   模板会导致代码膨胀问题,也会导致编译时间变长。

  ② 出现模板编译错误时,错误信息非常凌乱,不易定位错误。

                                               创作不易,点个赞呗,蟹蟹啦~

  • 23
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值