首页 > 其他分享 ><五>模板的完全特例化和非完全特例化

<五>模板的完全特例化和非完全特例化

时间:2022-12-06 17:48:01浏览次数:43  
标签:特例 MyVector cout public 化和非 class 模板

模板作为C++泛型编程的基础十分重要,其使得一份代码能用于处理多种数据类型。而有些时候,我们会希望对一些特定的数据类型执行不同的代码,这时就需要使用模板特例化(template specialization)。
函数模板特例化
首先说一个重要的,函数模板的特例化并不是函数重载,每一个特例化实际上是提供了另一个模板定义式,因此特例化不影响函数匹配。

特例化一个函数模板时,必须为模板中的每个参数都给出实参,关键字template后跟一个<>

类模板特例化
类模板中,提供所有实参时叫做全特化,类模板的全特化和函数模板的特例化上没有什么不同(除了一个是类模板一个是函数模板:D)

与函数模板必须为每个模板参数提供实参不同,类模板支持部分特例化,也叫偏特化(partial specialization)
当定义类模板的偏特化版本时,模板参数只需包含原模板中那些还未确定类型的模板参数,在类名之后需要添加<>,且需要按对应位置填入实参。

template<typename T, typename P>
class test {
public:
	test() { cout << "这是未特化的类模板\n"; }
};

template<typename P>//T被特化为bool类型,template<>中无需typename T
class test<bool,P> {
public:
	test() { cout << "这是bool偏特化的类模板\n"; }
};

template<>//全特化,template<>可以为空
class test<int*, int*> {
public:
	test(){ cout << "这是接受两个指针类型的全特化的类模板\n"; }
};

{
	test<int*, int> t1;//会调用未特化的类模板
	test<bool,int> t2;//会调用bool偏特化
	test<int*, int*> t3;//全特化版本
}
#include <iostream>

using namespace std;


template<typename T>
class MyVector {

public:
	MyVector<T>() { cout << "MyVector<T>()" << endl; }

};

//针对 char * 模板特例化
template<> 
class MyVector<char *> {

public:
	MyVector() { cout << "MyVector<char *>" << endl; }

};

//模板特例化,只针对指针类型提供的部分特例化,只知道指针,但是什么指针不知道
template<typename Ty>
class MyVector<Ty*> {

public:
	MyVector() { cout << "MyVector<Ty *>" << endl; }

};

//template<>
//class MyVector<int(*)(int, int)> {
//public:
//	MyVector() { cout << "int (*)(int,int )" << endl; }
//
//};

//template<typename T>
//class MyVector<T(*)(T, T)> {
//public:
//	MyVector() { cout << "MyVector<T(*)(T, T)>" << endl; }
//
//};
//
//template<typename R1, typename R2, typename R3>
//class MyVector<R1(*)(R2, R3)> {
//	public:
//		MyVector() { cout << "MyVector<R1(*)(R2, R3)>" << endl; }
//
//};


//template<typename R1, typename R2, typename R3>
//class MyVector<R1(R2, R3)> {
//	public:
//		MyVector() { cout << "MyVector<R1(R2, R3)>" << endl; }
//
//};

int sum(int x, int y) {
	return x + y;
}

int main() {

	MyVector<int> v1; //缺省模板

	MyVector<char *> v2;// char * 特例化模板

	MyVector<int *> v3;// 使用部分特例化 class MyVector<Ty*>



	MyVector<int (*)(int,int)> v4; // 使用部分特例化 class MyVector<Ty*> ,int (*)(int,int) 指向函数的指针

    // 如何针对 MyVector<int (*)(int,int)> v4;写一个完全特例化版本? 写法如下
	/* 
		template<>
		class MyVector<int(*)(int, int)> {
		public:
			MyVector() { cout << "int (*)(int,int )" << endl; }

		};
	*/

	// 如何针对 MyVector<int (*)(int,int)> v4;写一个部分特例化版本? 写法如下 两种
	
	/*  写法1
	    MyVector 元素是函数指针,返回类型是R1,两个参数类型分别是R2,R3  提供部分特例化
		template<typename T>
		class MyVector<T(*)(T, T)> {
		public:
			MyVector() { cout << "MyVector<T(*)(T, T)>" << endl; }

		};
	*/

	/*
		写法2
		MyVector 元素是函数指针,返回类型是R1,两个参数类型分别是R2,R3 提供部分特例化 
		template<typename R1, typename R2, typename R3>
		class MyVector< R1(*)(R2, R3) > 
		{
		public:
			MyVector() { cout << "MyVector<R1(*)(R2, R3)>" << endl; }

		};
	*/



	MyVector<int(int, int)> v5; //元素是函数对象类型,使用默认的函数版本,也可以使用如下方式

	/* 
	template<typename R1, typename R2, typename R3>
	class MyVector<R1(R2, R3)>//针对函数类型,进行部分特例化,有一个返回值,有两个形参
	{
	public:
		MyVector() { cout << "MyVector<R1(R2, R3)>" << endl; }

	};
	*/



	//函数指针类型
	typedef int (*PFUNCTION) (int, int);
	PFUNCTION pf1 = sum;
	pf1(12, 13);

	//函数类型
	typedef int PFUNCTION2 (int, int);
	PFUNCTION2 * pf2 = &sum;
	(*pf2)(12, 13);


	system("pause");
	//有完全特例化能匹配就用完全特例化版本,有部分特例化版本就用部分特例化,再没有就用缺省模板
	return 0;
}

//问题:这种写法可以,但是  typename T 这种方式  范围太大了!!优化如下
template<typename T>
void function(T _t) {
	cout << typeid(T).name() << endl;
}


template<typename R, typename R1, typename R2>
//细分到可以取出返回值类型R1,形参1类型R2,形参2类型R3  还可以继续细分 如下
void function(R1(*)(R2,R3)) {

	cout << typeid(R1).name() << endl; 
	cout << typeid(R2).name() << endl;
	cout << typeid(R3).name() << endl;

}

//效果,继续细分到可以取出返回值类型R1,哪个类类型T,形参1类型R1,形参2类型R2  Good
template<typename R, typename T, typename R1, typename R2>

void function3(R1(T::*)(R2, R3)) {

	cout << typeid(T).name() << endl;
	cout << typeid(R1).name() << endl;
	cout << typeid(R2).name() << endl;
	cout << typeid(R3).name() << endl;

}


class Test {


public:
	int sum(int x, int y) { return x + y; }

};

int main() {

	function3(&Test::sum);
}

标签:特例,MyVector,cout,public,化和非,class,模板
From: https://www.cnblogs.com/erichome/p/16955563.html

相关文章

  • 实验六 模板和文件IO
    task3_11#include<iostream>2#include<fstream>3#include<array>4#defineN556intmain(){7usingnamespacestd;89array<int,......
  • vue(13)在模板中使用slot插槽排序
    序Slot插槽插槽就是父组件往子组件中插入一些内容。有三种方式,默认插槽,具名插槽,作用域插槽默认插槽就是把父组件中的数据,显示在子组件中,子组件通过一个slot插槽标签显......
  • [c++11新特性]02-模板优化
    模板优化​模板优化​​​模板别名​​​​默认模板参数​​​​外部模板​​模板别名在了解类型别名模板之前,需要理解『模板』和『类型』之间的不同。仔细体会这句话:模板是......
  • [c++11新特性]07-可变参模板
    可变参模板​​可变参数模板​​​可变参模板​​​简介​​​​递归模板函数​​简介可变参模板是c++11引入的特别重要的一个特性,和c语言中的可变参一样,也是使用...来......
  • Python全栈工程师之从网页搭建入门到Flask全栈项目实战(4) - Flask模板语法与继承
    1.Flask模板介绍前置:理解渲染机制即上篇笔记中render_template()功能是如何实现的!1)找到html文件地址2)读取html文件中的内容3)替换html中的特殊字符4)将html的内容发送给......
  • MAUI新生3.3-深入理解XAML:控件模板ControlTemplate
    如本章前两节所述,可绑定属性仅仅定义了控件的数据状态,在UI层面并没有实际意义。要实现一个完整的UI控件,还需要使用控件模板来创建外观样式。如果从Vue或Blazor的组件化来理......
  • XMind 2022软件 及2000+最全模板素材大全 ( 12.5 亲测有效 )
    XMind2022安装下载教程下载直通车:立即下载模板素材视频直通车:获取XMind安装教程解压文件鼠标右击【XMind2022(64bit)】压缩包(win11系统需先点击“显示更多选项”)选......
  • 实验6模板类和文件IO
    task3-1.cpp#include<iostream>#include<fstream>#include<array>#defineN5intmain(){usingnamespacestd;array<int,N>x{97,98,99,100,101......
  • vue3 webstorm 快捷新建组建模板
          <template><h1>${COMPONENT_NAME}</h1></template><scriptlang="ts"setup>import{reactive}from'vue';import{useRouter}from"vue......
  • CodeSmith部署安装以及编写MySQL模板的时候无法获取description
    最近需要使用VS2015开发新项目,由于考虑到后期的扩展性,打算使用EF的codefirst模式来编写,但是前期又设计好了数据库结构,不想大动干戈的去重新写代码,网上搜索了说用“EntityF......