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

将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;
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/257368.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CCF刷题记录 -- 202305-2:矩阵运算 --python解法

2023.12.7 主要算法 矩阵置换矩阵相乘 满分注意点 运算顺序&#xff0c;利用了矩阵运算法则中的&#xff08;A*B&#xff09;*c A*(B*C) # 矩阵置换 def zhihuan(a):b[]for i in range(d):c []for j in range(n):c.append(a[j][i])b.append(c)return b# 矩阵相乘 def ju_zh…

高级多层次搭建企业级大数据项目, 成就全能型大数据开发实战经验思想

随着大数据技术的快速发展&#xff0c;企业越来越重视构建高效、可靠的大数据项目。本文将重点介绍如何高级多层次地搭建企业级大数据项目&#xff0c;并分享成为全能型大数据开发者的实战经验与思想。通过学习和应用这些技术&#xff0c;我们可以提升大数据项目的质量和效果。…

探索Vue小程序框架的底层原理

最近晚上有时间复盘之前研究小程序框架的相关内容&#xff0c;总结文章记录一下。 本篇文章主要介绍百度19年开源的Mars小程序开发框架&#xff0c;和Taro、mpvue、uniapp类似&#xff0c;都是编译型小程序框架&#xff0c;都是通过将 Vue 或 React 源码直接编译为小程序源码&a…

数据库字段名和sql关键字冲突报错解决方法

1、修改实体类字段映射。注解里加反引号 2、sql字段上加反引号 3、问题解决

MySQL_4.mysql数据库的安装(超详细——保姆级)

1.mysql 单实例、多实例安装 端口&#xff1a;&#xff08;3306、3307&#xff09; 环境&#xff1a;win11/win10 , mysql_5.7.30 2.安装Windows VC 、NET4.0 等系统组件 下载链接百度网盘: 链接&#xff1a;https://pan.baidu.com/s/1goIbaJ6YC-DzmBbVDyOolg 提取码&…

IPTABLES(一)

文章目录 1. iptables基本介绍1.1 什么是防火墙1.2 防火墙种类1.3 iptables介绍1.4 包过滤防火墙1.5 包过滤防火墙如何实现 2. iptables链的概念2.1 什么是链2.2 iptables有哪些链 3. iptables表的概念3.1 什么是表3.2 表的功能3.3 表与链的关系 4. iptables规则管理4.1 什么是…

将单体应用程序迁移到微服务

多年来&#xff0c;我处理过多个单体应用&#xff0c;并将其中一些迁移到了微服务架构。我打算写下我所学到的东西以及我从经验中用到的策略&#xff0c;以实现成功的迁移。在这篇文章中&#xff0c;我将以AWS为例&#xff0c;但基本原则保持不变&#xff0c;可用于任何类型的基…

vue2+datav可视化数据大屏(2)

接上一节所说 我们已经讲骨架搭好 这节我们讲述的如何在vue2中使用mock数据和封装axios 1&#xff0c;项目中使用moke &#x1f4d3;什么是mock&#xff1f;&#xff0c;mock就是假数据&#xff0c;除了数据是假的&#xff0c;其他内容都和正常工作中后端开发的接口都是一致的…

JavaScript实战:制作一个待办事项列表应用

JavaScript实战&#xff1a;制作一个待办事项列表应用 引言 在本教程中&#xff0c;我们将一步步创建一个简单的待办事项列表应用&#xff0c;这不仅会帮助你学习基本的JavaScript编程概念&#xff0c;还会教会你如何处理事件以及操作DOM。这个项目是面向初学者的&#xff0c…

Zookeeper单机模式搭建

1、下载 ​wget https://dlcdn.apache.org/zookeeper/zookeeper-3.6.3/apache-zookeeper-3.6.3-bin.tar.gz 2、解压 tar -zxvf apache-zookeeper-3.6.3-bin.tar.gz 3、进入 apache-zookeeper-3.6.3-bin目录下&#xff0c;创建data cd apache-zookeeper-3.6.3-bin mkdir da…

makefile中选项说明

-C gcc的-c选项表示只编译不链接。不带-c选项则默认既编译又链接。 CFLAGS编译参数 LDFLAGS链接参数 指定LIBS是要链接的库的目录。LDFLAGS告诉链接器从哪里寻找库文件。 LDFLAGS指定-L虽然能让链接器找到库进行链接&#xff0c;但是运行时链接器却找不到这个库&#xff0c;…

Docker安装postgres最新版

1. postgres数据库 PostgreSQL是一种开源的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它是一种高度可扩展的、可靠的、功能丰富的数据库系统。以下是关于PostgreSQL的一些介绍&#xff1a; 开源性&#xff1a;PostgreSQL是一个开源项目&#xff0c;可以…