【C++模板与泛型编程】系列之类模板

类模板

  引入类模板的目的是为了解决C++实现中减少代码冗余,这点与函数模板原因一致。

基本示例:类模板、静态函数、一般函数实例化。

  C++17中类模板的类型模板参数可以进行推断。(1) 隐式推断指南;(2) 自定义推断指南;

namespace _nsp2
{
	template <typename T>
	struct A
	{
		A(T val1, T val2)
		{
			std::cout << "val 1: " << val1 << ", 2: " << val2 << endl;
		}
		
		A(T val)
		{
			std::cout << "val : " << val << std::endl;
		}
	};
}

// _nsp2::A obj(5,6); // 这里推断出T为int
// _nsp2::A obj2(12.8); // 这里隐式推断出T为double
// _nsp2::A obj3(5, 6.9); // 类模板推断二义性,报错

  针对类模板的构造函数都存在一个隐式的目标推断指南

namespace _nsp3
{
	template <typename T>
	struct B
	{
		T m_b;
	};
	template <typename T>
	B(T)->B<T>; // 自定义推断指南
}

// _nsp3::B<int> b; // 需要指定int
// _nsp3::B<int> b2{12}; // 初始化列表的方式来定义 m_b 15
// _nsp3::B b3(15); //上述存在自定义推断指南才可以之本句可执行

  自定义推断指南,上述类对象 b 3 b_3 b3不会报错原因,1 类B是聚合类C++聚合类,可以通过{}进行初始化;2 因为上述自定义推断指南的存在;

类模板使用规则

  特化的类模板是通过泛化的类模板生成。因此,先有泛化类模板,才有特化版本的类模板。

类模板特化

  类模板的特化分为全特化偏特化两种方式。所谓全特化类模板就是所有类模板的变量都特化,而偏特化类模板就是特化部分变量或者变量的作用域范围有所改变

类模板全特化

namespace nsp4
{
	// 泛化版本
	template <typename T, typename U>
	struct TC
	{
		TC()
		{
			std::cout << "泛化版本..." << std::endl;
		}
		
		void fun()
		{
			std::cout << "fun()泛化版本..." << std::endl;
		}
	}
	//---------------------
	template <> //全特化:所有类型模板参数都存在具体代表
	struct TC<int , int>
	{
		TC()
		{
			std::cout << "全特化版本..." << std::endl;
		}
		
		void fun()
		{
			std::cout << "fun()全特化版本..." << std::endl;
		}
	}
}

// _nsp4::TC<int, double> tc1;
// tc1.fun();  // 泛化版本

// _nsp4::TC<int, int> tc2;
// tc2.fun();  // 全特化版本  // 如果没有全特化版本,将会调用泛化版本

普通成员函数全特化

  普通成员函数全特化版本,就是对全特化的某个类模板的成员函数重新定义下,见下面代码所示。

namespace nsp4
{
	// 泛化版本
	template <typename T, typename U>
	struct TC
	{
		TC()
		{
			std::cout << "泛化版本..." << std::endl;
		}
		
		void fun()
		{
			std::cout << "fun()泛化版本..." << std::endl;
		}
	};
	//--------------------
	template <>
	void TC<double, int>::fun()
	{
		std::cout << "普通成员函数fun()全特化版本..." << std::endl;
	}
}

// _nsp4::TC<double, int> tc4;
// tc4.fun();

静态成员变量全特化

  静态成员函数全特化原理与普通成员函数全特化类似,就是全特化某一个类版本后重新定义一下静态成员变量。

namespace nsp4
{
	// 泛化版本
	template <typename T, typename U>
	struct TC
	{
		TC()
		{
			std::cout << "泛化版本..." << std::endl;
		}
		
		void fun()
		{
			std::cout << "fun()泛化版本..." << std::endl;
		}
		static int m_age; // 静态成员变量
	};

	//-----------------
	template <typename T, typename U>
	int TC<T, U>::m_age = 50;	

	template <>
	int TC<double, int>::m_age = 100;
}

  如果使用成员函数全特化静态成员变量的全特化,就无法在对类进行全特化,因为重复全特化;

类模板偏特化

  类模板的偏特化主要有以下两个方面:一个是类模板参数变量的偏特化;另外一个是类模板参数范围上的偏特化;

模板参数数量上的偏特化

  类模板参数变量上的偏特化理解较为简单,就是存在某个固定变量类型,其它变量未确定的偏特化类模板。见下述代码:

namespace nsp4
{
	// 泛化版本
	template <typename T, typename U>
	struct TC
	{
		TC()
		{
			std::cout << "泛化版本..." << std::endl;
		}
		
		void fun()
		{
			std::cout << "fun()泛化版本..." << std::endl;
		}
		static int m_age; // 静态成员变量
	};

	//-----------------
	template <typename U>
	struct TC<float, U>
	{
		std::cout << "TC<float, U>偏特化版本..." << std::endl;
	}
    
    void TC<float, U>::fun()
    {
		std::cout << "TC<float, U>::fun()偏特化版本..." << std::endl;
	}
}

// _nsp4::TC<double, int> tc4;
// tc4.fun(); // 泛化

// _nsp4::TC<float, int> tc4;
// tc4.fun(); // 偏特化
模板参数范围上的偏特化

  类模板参数范围上的偏特化,主要是指:变量作用域变小。例如: T → c o n s t T T\rightarrow{const T} TconstT T → T ∗ T\rightarrow{T^*} TT等。

namespace nsp4
{
	// 泛化版本
	template <typename T, typename U>
	struct TC
	{
		TC()
		{
			std::cout << "泛化版本..." << std::endl;
		}
		
		void fun()
		{
			std::cout << "fun()泛化版本..." << std::endl;
		}
		static int m_age; // 静态成员变量
	};

	//-----------------
	template <typename T, typename U>
	struct TC<const T, U*>
	{
		std::cout << "TC<const T, U*>偏特化范围版本..." << std::endl;
	}

	template <typename T, typename U>
	void struct TC<const T, U*>::fun()
	{
		std::cout << "TC<const T, U*>::fun()偏特化版本..." << std::endl;
	}

}

// _nsp4::TC<double, int> tc4;
// tc4.fun(); // 泛化版本
// _nsp4::TC<const double, int*> tc4;
// tc4.fun(); // 偏特化版本

小结

  本篇主要记录一下类模板基本概念以及类模板特化的一些方式方法。留作后续查询记录,如果对你有所帮助深感喜悦。

参考

c++聚合类
51cto-类模板课程

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值