C++模板全特化(具体化)与偏特化(部分具体化)详解(转)

1.模板简介

模板就是实现代码重用的一种机制,它可以实现类型参数化,即把类型定义为参数, 从而实现了真正的代码可重用性。

模板编程和函数重载可以实现C++静态多态,也叫编译时多态

模版可以分为两类,一个是 函数模版 ,另一个是 类模版

2.模板特化的目的

模板本来是一组通用逻辑的实现,但是可能存在特定的参数类型下,通用的逻辑实现不能满足要求,这时就需要针对这些特殊的类型,而实现一个特例模板—即模板特化。

3.重点注意

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

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

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

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

5)注意模板编程不支持分离式编译,即模板类/模板函数的声明与定义应该放在头文件里,否则会在链接时报错;

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

常规函数 > 具体化模板函数 > 常规模板函数;

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

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

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

4.函数模板

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;

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

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

{.....}

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

{.....}

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

{.....}

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

Compare("1", "2");

会打印输出:

这里显示实际调用了全特化函数模板c,

因为在调用Compare("1", "2")时,先会进行重载决议

发生重载决议,会无视特化存在(标准规定:重载决议无视模板特化,重载决议发生在主模板之间),

那么就会决议出函数主模板b,在判断函数主模板存在符合类型条件的全特化模板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)函数模板全部实现

/******************************* 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 ****************************************/

打印输出如下图,

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 ****************************************/

执行后打印输出如下图所示,

可以看到MyClass<int, int>类型声明的对象,函数Compare地址是一样的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值