模板的特化(具体化)

模板的特化(具体化)

重点注意

1)类模板和函数模板都可以被全特化;

2)类模板能偏特化,不能被重载;

3)函数模板可以实现重载,不能被偏特化;

4)类模板调用优先级:全特化类>偏特化类>主版本模板类;

6)函数模板同时存在具体化模板、函数模板重载、和常规函数重载时候,调用优先级:

常规函数 > 具体化模板函数 > 常规模板函数;《这不是比较顺序,而是优先级》

注意:重载决议时,优先决议出是不是符合常规函数,不存在符合的普通函数,才会再决议出符合的函数主模板,对于函数模板重载决议,会无视特化存在(标准规定:重载决议无视模板特化,重载决议发生在主模板之间),决议出函数主模板后,如果函数主模板存在符合的具体化函数模板,才会调用具体化函数模板;

7)不能将函数模板特化和重载混为一谈
函数特化都没有引入一个全新的模板或者模板实例,它们只是对原来的主(或者非特化)模板中已经隐式声明的实例提供另一种定义。在概念上,这是一个相对比较重要的现象,也是特化区别于重载模板的关键之处。

如果使用普通重载函数,那么不管是否发生实际的函数调用,都会在目标文件中生成该函数的二进制代码。而如果使用函数模板特化版本,除非发生函数调用,否则不会在目标文件中包含特化模板函数的二进制代码。这符合函数模板的“惰性实例化”准则。

8>特化可以改变函数体

函数模板

1)常规函数

// 常规函数
void Compare(const char* first, const char* second)
{
	cout << "const char* ordinary function " << endl;
	if (strcmp(first, second) > 0) // 比较char*,需要区别函数主模板进行处理
	{
		cout << "first:" << first << " > second:" << second << endl;
	}
	else
	{
		cout << "first:" << first << " <= second:" << second << endl;
	}
}

2)函数主模板a

//函数主模板
template<typename T, typename N> void Compare(T first, N second)
{
	cout << "Standard function template <T, N>" << endl;
	if (first < second)
	{
		cout << "first < second" << endl;
	}
	else
	{
		cout << "first >= second" << endl;
	}
}

3)函数模本b–全特化

//针对char*类型的比较函数,不能直接使用大于号或小于号比较元素,需要特化;
//函数模板-全特化
template<> void Compare(const char* first, const char* second)
{
	cout << "const char* specialization <const char*, const char*>" << endl;
	if (strcmp(first, second) > 0) // 比较char*,需要区别函数主模板进行处理
	{
		cout << "first:" << first << " > second:" << second << endl;
	}
	else
	{
		cout << "first:" << first << " <= second:" << second << endl;
	}
}

4)函数模板c-重载,作为一个独立的函数主模板

//函数模板-重载,不是偏特化,它会作为一个独立的函数主模板
template<typename T, typename N> void Compare(T* first, N* second)
{
	cout << "function template overload <T*, N*>" << endl;
	cout << "T type: " << typeid(T).name() << ", N type : " << typeid(N).name() << endl;
	if (strcmp(typeid(T).name(), "char") == 0 && strcmp(typeid(N).name(), "char") == 0)
	{
		if (strcmp(first, second) > 0) // 比较char*,需要区别函数主模板进行处理
		{
			cout << "first:" << first << " > second:" << second << endl;
		}
		else
		{
			cout << "first:" << first << " <= second:" << second << endl;
		}
	}
	else
	{
		if (*first < *second)
		{
			cout << "first < second" << endl;
		}
		else
		{
			cout << "first >= second" << endl;
		}
	}
}

5)函数模板之间的重载决议

1】当代码中存在如下顺序的申明时,

template<typename T, typename N> void Compare(T first, N second) //函数主模板a

{.....}

template<> void Compare(const char* first, const char* second) // 函数主模板a的全特化模板 b

{.....}

template<typename T, typename N> void Compare(T* first, N* second) // 函数主模板c,是函数主模板a的重载

{.....}

那么,发生如下函数调用时,

Compare("1", "2");
函数将调用函数主模板c
    

因为在调用Compare("1", "2")时,先会进行重载决议,
发生重载决议,会无视特化存在(标准规定:重载决议无视模板特化,重载决议发生在主模板之间),
那么就会决议出函数主模板c;
那将会调用函数主模板c
    
    《根据第六条,:重载决议时,优先决议出是不是符合常规函数,不存在符合的普通函数,才会再决议出符合的函数主模板,对于函数模板重载决议,会无视特化存在(标准规定:重载决议无视模板特化,重载决议发生在主模板之间),决议出函数主模板后,如果函数主模板存在符合的具体化函数模板,才会调用具体化函数模板;》
    

6)常规函数与函数模板之间的重载决议

当代码中存在如下顺序的申明时,

template<typename T, typename N> void Compare(T first, N second) //函数主模板a

{.....}

template<> void Compare(const char* first, const char* second) // 函数主模板a的全特化模板 b

{.....}

template<typename T, typename N> void Compare(T* first, N* second) // 函数主模板c,是函数主模板a的重载

{.....}
void Compare(const char* first, const char* second) // 常规函数

{.....}

那么,发生如下函数调用时,

Compare("1", "2");

函数将调用常规函数
    
因为在调用Compare("1", "2")时,先会进行重载决议,重载决议会优先决议是否存在符合条件的常规函数。
    

7)函数模板全部实现


#include<iostream>
using namespace std;
#include<string.h>
#include<vector>

/******************************* template function start ****************************************/
 
//函数主模板
template<typename T, typename N> void Compare(T first, N second)
{
	cout << "Standard function template <T, N>" << endl;
	if (first < second)
	{
		cout << "first < second" << endl;
	}
	else
	{
		cout << "first >= second" << endl;
	}
	cout << endl;
}
 
//函数模板-全特化
template<> void Compare(const char* first, const char* second)
{
	cout << "const char* specialization <const char*, const char*>" << endl;
	if (strcmp(first, second) > 0) // 比较char*,需要区别函数主模板进行处理
	{
		cout << "first:" << first << " > second:" << second << endl;
	}
	else
	{
		cout << "first:" << first << " <= second:" << second << endl;
	}
	cout << endl;
}
 
//函数主模板-重载,不是偏特化,它会作为一个独立的函数主模板
template<typename N> void Compare(int first, N second)
{
	cout << "partitial specialization <int, N>" << endl;
	if (first < second)
	{
		cout << "first < second" << endl;
	}
	else
	{
		cout << "first >= second" << endl;
	}
	cout << endl;
}
 
//函数模板-重载,不是偏特化,它会作为一个独立的函数主模板
template<typename T, typename N> void Compare(T* first, N* second)
{
	cout << "function template overload <T*, N*>" << endl;
	cout << "T type: " << typeid(T).name() << ", N type : " << typeid(N).name() << endl;
	if (strcmp(typeid(T).name(), "char") == 0 && strcmp(typeid(N).name(), "char") == 0)
	{
		if (strcmp(first, second) > 0) // 比较char*,需要区别函数主模板进行处理
		{
			cout << "first:" << first << " > second:" << second << endl;
		}
		else
		{
			cout << "first:" << first << " <= second:" << second << endl;
		}
	}
	else
	{
		if (*first < *second)
		{
			cout << "first < second" << endl;
		}
		else
		{
			cout << "first >= second" << endl;
		}
	}
	cout << endl;
}
 
//函数主模板-重载,不是偏特化,它会作为一个独立的函数主模板
template<typename T, typename N> void Compare(std::vector<T>& first, std::vector<N>& second)
{
	cout << "to vector partitial specialization <std::vector,std::vector>" << endl;
	if (first.size() < second.size())
	{
		cout << "first.size() < second.size()" << endl;
	}
	else
	{
		cout << "first.size() >= second.size()" << endl;
	}
	cout << endl;
}
 
// 常规函数
void Compare(const char* first, const char* second)
{
	cout << "const char* ordinary function " << endl;
	if (strcmp(first, second) > 0) // 比较char*,需要区别函数主模板进行处理
	{
		cout << "first:" << first << " > second:" << second << endl;
	}
	else
	{
		cout << "first:" << first << " <= second:" << second << endl;
	}
	cout << endl;
}
 
// 测试函数模板功能
void Test_Temmplate_Function()
{
	cout << __FUNCTION__ << ":" << endl;
	Compare(1,2);
	Compare(1, 2.0);
	Compare(1.0, 2.0);
	Compare('1', '2');
	Compare("1", "2");
	vector<int> v1 = { 1 };
	vector<int> v2 = { 2 };
	Compare(v1, v2);
	cout << endl;
}
 
/******************************* template function end ****************************************/

int main()
{
    Test_Temmplate_Function();
}

//输出结果

Test_Temmplate_Function:
partitial specialization <int, N>
first < second

partitial specialization <int, N>
first < second

Standard function template <T, N>
first < second

Standard function template <T, N>
first < second

const char* ordinary function 
first:1 <= second:2

to vector partitial specialization <std::vector,std::vector>
first.size() >= second.size()

5.类模板

必须先有泛化版本类模板(主模板),才有特化版本类模板。

1)类模板特化分类

特化为绝对类型(全特化);

特化为引用,指针类型(半特化、偏特化);

特化为另外一个类模板(复杂点的偏特化)

2)类模板-主模板类

//类模板-主版本模板类
template<typename T, typename N> class MyClass
{
public:
	 void Compare(T first, N second)
	{
		cout << "standard function template" << endl;
		cout << __FUNCTION__ << ":" << endl;
		if (first < second)
		{
			cout << "first < second" << endl;
		}
		else
		{
			cout << "first >= second" << endl;
		}
	}
};

3)类模板-全特化(具体化)

//类模板-全特化(具体化)
template<> class MyClass<const char*, const char*>
{
public:
	 void Compare(const char* first, const char* second)
	{
		cout << "const char* specialization" << endl;
		cout << __FUNCTION__ << ":" << endl;
		if (strcmp(first, second) > 0) // 比较char*,需要区别函数主模板进行处理
		{
			cout << "first:" << first << " > second:" << second << endl;
		}
		else
		{
			cout << "first:" << first << " <= second:" << second << endl;
		}
	}
};

4)类模板-特化(部分具体化),对部分模板参数进行特化为一般类型

//类模板-特化(部分具体化),对部分模板参数进行特化
template<typename N> class MyClass<int, N>
{
public:
	void Compare(int first, N second)
	{
		cout << "partitial specialization" << endl;
		cout << __FUNCTION__ << ":" << endl;
		if (first < second)
		{
			cout << "first < second" << endl;
		}
		else
		{
			cout << "first >= second" << endl;
		}
	}
};

5)类模板-特化(部分具体化),将模板参数特化为指针

//类模板-特化(部分具体化),将模板参数特化为指针
template<typename T, typename N> class MyClass<T*, N*>
{
public:
	 void Compare(T* first, N* second)
	{
		cout << "ptr partitial specialization" << endl;
		cout << __FUNCTION__ << ":" << endl;
		if (first < second)
		{
			cout << "first < second" << endl;
		}
		else
		{
			cout << "first >= second" << endl;
		}
	}
};

6)类模板-特化(部分具体化),将模板参数特化为另一个模板类

//类模板-特化(部分具体化),将模板参数特化为另一个模板类
template<typename T, typename N> class MyClass<vector<T>, vector<N>>
{
public:
	void Compare(const vector<T>& first, const vector<N>& second)
	{
		cout << "to vector partitial specialization" << endl;
		cout << __FUNCTION__ << ":" << endl;
		if (first.size() < second.size())
		{
			cout << "first.size < second.size" << endl;
		}
		else
		{
			cout << "first.size >= second.size" << endl;
		}
	}
};

7)类模板特化全部实现

 
/******************************* template class start ****************************************/
 
//类模板-主版本模板类
template<typename T, typename N> class MyClass
{
public:
	 void Compare(T first, N second)
	{
		cout << "standard function template" << endl;
		cout << __FUNCTION__ << ":" << endl;
		if (first < second)
		{
			cout << "first < second" << endl;
		}
		else
		{
			cout << "first >= second" << endl;
		}
	}
};
 
//类模板-全特化(具体化)
template<> class MyClass<const char*, const char*>
{
public:
	 void Compare(const char* first, const char* second)
	{
		cout << "const char* specialization" << endl;
		cout << __FUNCTION__ << ":" << endl;
		if (strcmp(first, second) > 0) // 比较char*,需要区别函数主模板进行处理
		{
			cout << "first:" << first << " > second:" << second << endl;
		}
		else
		{
			cout << "first:" << first << " <= second:" << second << endl;
		}
	}
};
 
//类模板-特化(部分具体化),对部分模板参数进行特化
template<typename N> class MyClass<int, N>
{
public:
	void Compare(int first, N second)
	{
		cout << "partitial specialization" << endl;
		cout << __FUNCTION__ << ":" << endl;
		if (first < second)
		{
			cout << "first < second" << endl;
		}
		else
		{
			cout << "first >= second" << endl;
		}
	}
};
 
//类模板-特化(部分具体化),将模板参数特化为指针
template<typename T, typename N> class MyClass<T*, N*>
{
public:
	 void Compare(T* first, N* second)
	{
		cout << "ptr partitial specialization" << endl;
		cout << __FUNCTION__ << ":" << endl;
		if (first < second)
		{
			cout << "first < second" << endl;
		}
		else
		{
			cout << "first >= second" << endl;
		}
	}
};
 
//类模板-特化(部分具体化),将模板参数特化为另一个模板类
template<typename T, typename N> class MyClass<vector<T>, vector<N>>
{
public:
	void Compare(const vector<T>& first, const vector<N>& second)
	{
		cout << "to vector partitial specialization" << endl;
		cout << __FUNCTION__ << ":" << endl;
		if (first.size() < second.size())
		{
			cout << "first.size < second.size" << endl;
		}
		else
		{
			cout << "first.size >= second.size" << endl;
		}
	}
};
 
// 测试类模板功能
void Test_Temmplate_Class()
{
	cout << __FUNCTION__ << ":" << endl;
 
	MyClass<char, int> c_i_myclass;
	c_i_myclass.Compare(1, 2);
	printf("function address: %p\n\n", &MyClass<char,int>::Compare);
 
	MyClass<int, double> i_d_myclass;
	i_d_myclass.Compare(1, 2);
	printf("function address: %p\n\n", &MyClass<int, double>::Compare);
 
	MyClass<int, int> i_i_myclass1;
	i_i_myclass1.Compare(1, 2);
	printf("function address: %p\n\n", &MyClass<int, int>::Compare);
 
	MyClass<int, int> i_i_myclass2;
	i_i_myclass2.Compare(1, 2);
	printf("function address: %p\n\n", &MyClass<int, int>::Compare);
 
	MyClass<const char*, const char*> c_c_c_c_myclass;
	c_c_c_c_myclass.Compare("1", "2");
	printf("function address: %p\n\n", &MyClass<const char*, const char*>::Compare);
 
	MyClass<vector<int>, vector<char>> vc_i_vc_c_maclass;
	vc_i_vc_c_maclass.Compare({ 1 }, { 1,2 });
	printf("function address: %p\n\n", &MyClass<vector<int>, vector<char>>::Compare);
 
	cout << endl;
}
 
/******************************* template class end ****************************************/

运行结果

Test_Temmplate_Class:
standard function template
Compare:
first < second
function address: 0x5581ffb2399c

partitial specialization
Compare:
first < second
function address: 0x5581ffb23a84

partitial specialization
Compare:
first < second
function address: 0x5581ffb23b76

partitial specialization
Compare:
first < second
function address: 0x5581ffb23b76

const char* specialization
Compare:
first:1 <= second:2
function address: 0x5581ffb23834

to vector partitial specialization
Compare:
first.size < second.size
function address: 0x5581ffb23e8e
此外,特化的模板只在传入特定的参数时才会调用,否则调用主模板

//模板操作自定义类型:方法一采用重载函数,将<<重载为友元函数,能访问保护成员。也能打印对象
#include <iostream>
#include<string.h>
using namespace std;
template<class T>
void print(T object)
{
    cout<<object<<endl;
    cout<<" choose_this "<<endl;
}
class point
{

    friend  void print<point>(point object);
protected:
    int x;
    int y;
    string name;
//改正方法

public:
    point(int x, int y,string name):x(x),y(y),name(name){};

};
template<>
void print<point>(point object)
{
    cout<<object.x<<" "<<object.y<<" "<<object.name<<endl;
    cout<<" choose_that "<<endl;

}
int main()
{  print(255);
   cout<<"*****************************"<<endl;
    point pp(11,22,"x and y");
    //隐式调用
    print (pp);
}


调用结果

255
 choose_this 
*****************************
11 22 x and y
 choose_that 

特化的模板只有特定的参数才能被调用,否则不会

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

丁金金

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值