C++ 模板 Traits

写一个简单的累加模板,如下:

template<typename T>
T accum(T const* beg, T const* end)
{
	T total{};
	while(beg != end)
	{
		total += * beg;
		++ beg;
	}
	return total;
}


int main()
{

	int num[] = { 1, 2, 3, 4, 5 };
	std::cout << "the average value of the integer values is "
		<< accum(num, num + 5) / 5
		<<std::endl;

	char name[] = "templates"; 
	int length = sizeof(name) - 1;// (try to) print average character value
	std::cout << "the average value of the characters in \""
		<< name << "\" is "
		<< accum(name, name + length) / length << std::endl;
	return 0;
}

运行结果
在这里插入图片描述
很明显 当T为char类型是结果错误。

打印累加过程看看:
在这里插入图片描述

发现问题出在:
char类型的取值范围是 -128 ~ +127,

std::cout<<int(char(127))<<" "<< int(char(128)) << " " << int(char(129)) << std::endl;

输出是: 127 -128 -127

所以累加函数,当T为char类型时,T total{};代码的需要改成 int total{}
因为char类型的数据做累加的时候太容易超出取值范围,而产生数字溢出的错误了

模板特化

那怎么对char类型的数据特殊处理呢?

类似函数重载的思路,这里叫做 模板特化

#pragma once
#include<iostream>
// 特化的例子

// 首先,要写出模板的一般形式(原型)
template<typename T>
auto accum(T const* beg, T const* end)
{
	T total{};
	 
	while (beg != end)
	{
		total += *beg;
		++beg;
		 
	}
	return total;
}

// 其次,我们要指定T是char时候的代码,这就是特化:
template<>
auto accum<char>(char const* beg, char const* end)
{
	int total{};
	 
	while (beg != end)
	{
		total += *beg;
		++beg;
	 
	}
	return total;
}


 

测试:

int main()
{

	int num[] = { 1, 2, 3, 4, 5 };
	std::cout << "the average value of the integer values is "
		<< accum(num, num + 5) / 5
		<<std::endl;

	char name[] = "templates"; 
	int length = sizeof(name) - 1;// (try to) print average character value
	std::cout << "the average value of the characters in \""
		<< name << "\" is "
		<< accum(name, name + length) / length << std::endl;


	float dnum[] = { 1.1, 2.1, 3.1, 4.1, 5.1 };
	std::cout << "the average value of the integer values is "
		<< accum(dnum, dnum + 5) / 5.0
		<< std::endl;
	return 0;
}

结果:
在这里插入图片描述

可以看出 只有char类型的数据,调用的特化的模板

int 和double类型都调用的一般模板

Traits

这里也可以用Traits解决这个问题

#pragma once
template<typename T>
struct AccumulationTraits;

template< >
struct AccumulationTraits<char> 
{
	using AccT = int;
}; 

template<>
struct AccumulationTraits<short>
{
	using AccT = int;
}; 

template<>
struct AccumulationTraits<int>
{
	using AccT = long;
};
template<>
struct AccumulationTraits<unsigned int>
{
	 using AccT = unsigned long;
}; 
template<>
struct AccumulationTraits<float> 
{
	using AccT = double;
};


template<typename T>
auto accum(T const* beg, T const* end)
{
	// return type is traits of the element type
	using AccT = typename AccumulationTraits<T>::AccT;

	// assume this actually creates a zero value
	AccT total{};   
	
	while (beg != end) 
	{
		total += *beg;
		++beg;
	}

	return total;
}

该问题的核心解决思路是:根据不同的T ,初始化不同类型的total。

这里首先给出 模板的一般形式(原型)

template<typename T>
struct AccumulationTraits;

依次给出不同类型需要的total类型

template< >
struct AccumulationTraits<char> 
{
	using AccT = int;
}; 

假设是char类型 那么AccT 就是 int

auto accum(T const* beg, T const* end) 函数中:
使用

using AccT = typename AccumulationTraits<T>::AccT;

获取 想要的total类型,完成累加操作

参考文献
模板元编程基础
《C++ Templates》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值