C++新经典模板与泛型编程:将trait类模板用作模板参数

2023-12-13 06:13:10

将trait类模板用作模板参数

template<typename T>
struct SumFixedTraits;

template<>
struct SumFixedTraits<char>
{
	using sumT = int;
	static sumT initValue() {
		return 0;
	}
};

template<>
struct SumFixedTraits<int>
{
	using sumT = __int64;
	static sumT initValue() {
		return 0;
	}
};

template<>
struct SumFixedTraits<double>
{
	using sumT = double;
	static sumT initValue() {
		return 0.0;
	}
};

template<typename T>
auto funcsum(const T* begin, const T* end)
{
	using sumT = typename SumFixedTraits<T>::sumT;
	sumT sum = SumFixedTraits<T>::initValue();
	for (;;)
	{
		sum += (*begin);
		if (begin == end)
			break;
		++begin;
	}
	return sum;
}

funcsum()函数模板用于计算数组元素的和值。下面,给funcsum()函数模板增加一个模板参数以进一步增加funcsum()函数模板的灵活性。修改后的funcsum()函数模板代码如下。

template<typename T,typename U = SumFixedTraits<T>>
auto funcsum(const T* begin, const T* end)
{
	// using sumT = typename SumFixedTraits<T>::sumT;  本行不需要
	// sumT sum = SumFixedTraits<T>::initValue();  本行不需要
	typename U::sumT sum = U::initValue();

	for (;;)
	{
		sum += (*begin);
		if (begin == end)
			break;
		++begin;
	}
	return sum;
}

在上面的代码中,引入了第2个类型模板参数U,该模板参数有一个默认值,而且这个默认值可以通过第1个模板参数推断出来(第2个模板参数依赖于第1个模板参数),所以一般不需要指定。但如果有特殊的需求,也是可以指定的,这就增加了funcsum()函数模板使用时的灵活性。
main()主函数中以往的代码行如下。

	char my_char_array[] = "abc";
	std::cout << (int)(funcsum(&my_char_array[0], &my_char_array[2])) << std::endl;

上面这两行代码,在调用funcsum()时,第1个类型模板参数T被推断为char类型,第2个类型模板参数U就变成了SumFixedTraits类型。因此,funcsum()函数模板中的代码行:

typename U::sumT sum = U::initValue();

等价于:

typename SumFixedTraits<char>::sumT sum = SumFixedTraits<char>::initValue();

等价于:

int sum = 0;

也就是说,计算和值的时候,用于保存和值的sum变量int类型。如果希望用于保存和值的sum变量int类型变成__int64类型,怎么做呢?也是可以做到的,这就是引入类型模板参数U的灵活之处。
将代码行:

std::cout << (int)(funcsum(&my_char_array[0], &my_char_array[2])) << std::endl;

修改为:

std::cout << (int)(funcsum<char, SumFixedTraits<int>>(&my_char_array[0], &my_char_array[2])) << std::endl;

如果需要,还可以把funcsum()的第2个类型模板参数指定为一个完全不同的trait类模板,这完全由程序员自己决定。

完整代码,如下:

#include "killCmake.h"

#include<string>

using namespace std;

template<typename T>
struct SumFixedTraits;

template<>
struct SumFixedTraits<char>
{
	using sumT = int;
	static sumT initValue() {
		return 0;
	}
};

template<>
struct SumFixedTraits<int>
{
	using sumT = __int64;
	static sumT initValue() {
		return 0;
	}
};

template<>
struct SumFixedTraits<double>
{
	using sumT = double;
	static sumT initValue() {
		return 0.0;
	}
};

template<typename T,typename U = SumFixedTraits<T>>
auto funcsum(const T* begin, const T* end)
{
	// using sumT = typename SumFixedTraits<T>::sumT;  本行不需要
	// sumT sum = SumFixedTraits<T>::initValue();  本行不需要
	typename U::sumT sum = U::initValue();

	for (;;)
	{
		sum += (*begin);
		if (begin == end)
			break;
		++begin;
	}
	return sum;
}



int main()
{
	char my_char_array[] = "abc";
	std::cout << (int)(funcsum(&my_char_array[0], &my_char_array[2])) << std::endl;

	std::cout << (int)(funcsum<char, SumFixedTraits<int>>(&my_char_array[0], &my_char_array[2])) << std::endl;

	return 0;
}

在这里插入图片描述

文章来源:https://blog.csdn.net/qq_21381465/article/details/134869648
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。