• C++ 模板泛型编程


    1、函数模板

    概述,泛型编程,不局限于特点类型的方式编写代码,使用泛型编程需要指定实际操作的类型

    // typename 可以写成class,多个参数用,分割
    template<typename T>
    T fun(T a,T b)
    {
    	return a+b;
    }
    
    int a = fun(1,3);	// 通过实参推断出来
    
    // 非类型模板参数
    template<int a,int b>
    int fun2()
    {
    	return a+b;
    }
    
    fun2<1,2>();	// 显示指定模板参数
    
    template<T c,int a,int b>
    int fun3(T c)
    {
    	return (int)c +a+b;
    }
    fun3<int,11,22>(11);
    
    template<unsigned L1,unsigned L2>
    inline // 模板函数可以是内联函数,放在模板之后就行
    int fun4(const char (&p)[L1],const char (&p2)[L2])
    {
    }
    fun4("test","test2");// 系统会根据test,和test2自动推断出来L1和L2的长度,会计算结尾\0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    模板定义不会导致编译器生产代码,当函数调用时,编译器才会生产特点版本的代码,编译器生产代码是需要找到函数体,所以一般模板函数都写在.h中

    2、类模板

    浮点型不能作为非类型模板参数,类类型也不行

    template<class T>
    class myvector
    {
    public:
    	typedef T* myiterator;
    
    	myvector(const myvector& tmp)
    	{
    
    	}
    	myvector& operator=(const myvector&)
    	{
    
    	}
    
    	void fun();
    };
    
    template<class T>
    void myvector<T>::fun()
    {
    
    }
    
    
    // 非类型类模板参数
    template<class T,int T2>
    class A
    {
    public:
    	void fun();
    };
    
    template<class T,int T2>
    void A<T,T2>::fun()
    {
    }
    
    A<int,22> s1;
     
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    3、typename使用场合

    1、在模板定义中,其后模板参数时类型
    template
    2、使用类的类型成员,需要typename来标识这是一个类型

    template<class T>
    class myvector
    {
    public:
    	typedef T* myiterator;
    
    	myvector(const myvector& tmp)
    	{
    
    	}
    	myvector& operator=(const myvector&)
    	{
    
    	}
    public:
    	myiterator begin();
    	myiterator end();
    	void fun();
    };
    
    template<class T>
    typename myvector<T>::myiterator myvector<T>::begin()
    {
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    函数中

    template<typename T>
    typename T::size_type fun(const T& t)
    {
    	if(t.empty())
    	{
    		return 0;
    	}
    	return t.size();
    }
    
    string s1 = "hello world";
    string::size_type size = fun(s1);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4、函数指针做其他函数的参数

    typedef int(*FunPtr)(int,int);
    
    int my(int a,int b)
    {
    	return a+b;
    }
    
    void fun(int a,int b,FunPtr my)
    {
    	my(a,b);
    }
    
    fun(1,2,my);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    5、函数模板趣味例子

    1

    typedef int(*FunPtr)(int,int);
    
    int my(int a,int b)
    {
    	return a+b;
    }
    
    template<typename T,typename F>
    void fun(T a,T b,F my)
    {
    	F(a,b);
    }
    
    fun(1,2,my);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2

    class A
    {
    	A()
    	{
    		cout<<"A构造函数执行"<<endl;
    	}
    	A(const A& tmp)
    	{
    		cout<<"拷贝构造函数"<<endl;
    	}
    	int operator()(int x,int y)const
    	{
    		return x+y;
    	}
    }
    template<typename T,typename F>
    void fun(const T& a,const T& b,F my) 
    {
    	F(a,b);
    }
    // 会调用A的构造函数
    // A的拷贝构造函数,是因为将a对象传递给函数fun时触发
    
    A a;
    fun(1,2,a);
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    6、using 使用

    我们希望前面部分固定,后面通过指定

    c++ 98实现这种需求的方式
    template<typename ts>
    struct wt
    {
    	typedef std::map<std::string,ts> map_s_ts;
    };
    
    wt<int>::map_s_ts map1;	//相当于定义了一个map 类型
    
    // c++ 11 实现
    template<typename ts>
    using str_map_t = std::map<std::string,ts>;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    总结:using是新类型的别名

    7、可变参模板

    允许模板中含有0个,和多个,args我们称为一个包,多个参数可以为不同类型,

    // 1
    template<typename... T>
    void myfunc(T... args)
    {
    	cout<<sizeof...(args)<<endl;	// 打印可变参个数
    	cout<<sizeof...(T)<<endl;
    }
    
    myfunc();	// 表示0个参数
    myfunc(10,20,30)// 表示3个参数
    
    // 2
    template<typename U,typename... T>
    void myfunc1(U& u,T&... args)
    {
    	cout<<sizeof...(args)<<endl;	// 打印可变参个数
    }
    myfunc1(10);	// 至少有一个参数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    2、包参数展开

    void myfunc1()
    {
    	cout<<"递归终止函数"<<endl;
    }
    
    // 一个参数,一个包,最适合参数包展开,通过递归调用,每次将进来的第一个参数给u,其他参数继续调用
    template<typename U,typename... T>
    void myfunc1(U& u,T&... args)
    {
    	cout<<u<<endl;
    	myfunc1(args...); 
    }
    myfunc1(10);	// 至少有一个参数```
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
  • 相关阅读:
    【LeetCode-中等题】150. 逆波兰表达式求值
    万亿数据秒级响应,Apache Doris 在360 数科实时数仓中的应用
    Vue项目实战之人力资源平台系统(一)框架介绍及项目环境搭建
    自然语言处理(NLP)—— 神经网络语言处理
    jQuery学习:显示隐藏 --点击图片显示隐藏
    Docker 配置国内镜像加速器
    云原生—运行时环境
    Android 优化 - 磁盘缓存DiskLruCache
    JVM原理及优化_子系统
    电脑重装系统后当前安全设置不允许下载该文件
  • 原文地址:https://blog.csdn.net/weixin_45715405/article/details/126574177