C++泛型程序设计---算法和提升
算法和提升
算法:所谓算法就是一个求解问题的过程或公式,即,通过一个有穷的计算序列生成结果。
函数模板就是普通函数的泛化:它能对多种数据类型执行动作,并且能用以参数方式传递来的各种操作实现要执行的工作,函数模板通常也称为算法。
提升:从一个(多个可能更好)具体的实例中泛化出一个算法,使之能适用于最大(但合理)范围的实参类型,即,限制一个算法(或一个类)只依赖必要的属性。
提升算法是一个由具体到抽象的过程,最重要的一点是保持性能并注意如何做才是合理的,如果试图覆盖所有可能的类型和操作,可能会把泛化推到一个不合理的程度。因此试图在缺乏具体实例的情况下直接从基本原理进行抽象,通常会使代码臃肿不堪,难以使用。
以下展示从一个具体实例提升出算法的过程:
//计算实参数组中double值的和
double add_double(double *array, int n)
{
double sum{0};
for(int i = 0; i < n; ++i)
{
sum = sum + array[i];
}
return sum;
}
//计算vector<int>中所有int值的和
int add_vector(const std::vector<int> &vec)
{
int sum{0};
for(auto iter = vec.cbegin(); iter != vec.cend(); ++iter)
{
sum += *iter;
}
return sum;
}
以上代码给出了两个具体的算法,现在以这两个具体的算法未起点,逐步设计出一个通用的算法。
先确定一个抽象的目标:
- 不再明确说明元素是double还是int。
- 不再明确说明是数组还是向量。
以下为第一个抽象版本:
template<typename Iter, typename Val = double>
Val sum_v1(Iter first, Iter last) noexcept
{
Val sum = 0;
while(first != last)
{
sum = sum + (*first);
++first;
}
return sum;
}
//测试
vector<int> vec = {200, 2, 3, 4};
int sum1 = sum_v1<vector<int>::iterator, int>(vec.begin(), vec.end()); //sum1 = 209
double ad[] = {100.0, 2, 3, 4};
double sum2 = sum_v1(ad, ad + 4); //sum2 = 109
以上抽象出了一个通用版本, 但是类型参数Val不能自动推到获得,显式的指定Val有点不友好。
下面针对Val类型参数、运算符做进一步抽象
template<typename Iter, typename Val, typename Operator>
Val sum_v2(Iter first, Iter last, Val sum, Operator opr) noexcept
{
while(first != last)
{
sum = opr(sum, *first);
++first;
}
return sum;
}
//测试
vector<int> vec = {200, 2, 3, 4};
int sum = sum_v2(vec.begin(), vec.end(), 0, std::plus<int>());
double ad[] = {100.0, 2, 3, 4};
double product = sum_v2(ad, ad + 4, 1.0, std::multiplies<double>());
标准库对一些常见的运算,如plus、minus、multiplies,提供了对应的函数对象,可以作为实参。
设计算法最重要的指导原则是:在从具体实例提升算法的过程中,增加的特性(符号或运行时开销)不能损害算法的使用。
以下是标准库提供的plus函数对象
template<class _Ty = void>
struct plus
{
// functor for operator+
typedef _Ty first_argument_type;
typedef _Ty second_argument_type;
typedef _Ty result_type;
constexpr _Ty operator()(const _Ty& _Left, const _Ty& _Right) const
{
// apply operator+ to operands
return (_Left + _Right);
}
};
template<>
struct plus<void>
{
// transparent functor for operator+
typedef int is_transparent;
template<class _Ty1, class _Ty2>
constexpr auto operator()(_Ty1&& _Left, _Ty2&& _Right) const
-> decltype(static_cast<_Ty1&&>(_Left) + static_cast<_Ty2&&>(_Right))
{
// transparently apply operator+ to operands
return (static_cast<_Ty1&&>(_Left) + static_cast<_Ty2&&>(_Right));
}
};
C++泛型程序设计---算法和提升的更多相关文章
- C++学习笔记53:泛型程序设计与C++标准模板库
泛型程序设计的基本概念 编写不依赖于具体数据类型的程序 将算法从特定的数据结构中抽象出来,成为通用的 C++模板为泛型编程程序设计奠定了关键的基础 模型:符合一个概念的数据类型称为该概念的模型,例如: ...
- 8、泛型程序设计与c++标准模板库1、泛型程序设计的概念和术语
有效地利用已有的成果,将经典的.优秀的算法标准化.模块化,从而提高软件的生产率,是软件产业化的需求,为了实现这一需求,不仅需要面向对象设计思想,而且需要泛型程序设计思想. c++语言提供的标准模板库( ...
- C++ 泛型程序设计与STL模板库(1)---泛型程序设计简介及STL简介与结构
泛型程序设计的基本概念 编写不依赖于具体数据类型的程序 将算法从特定的数据结构中抽象出来,成为通用的 C++的模板为泛型程序设计奠定了关键的基础 术语:概念 用来界定具备一定功能的数据类型.例如: 将 ...
- 谈下程序设计算法的准备心得与体会-nCov隔离也许帮你提升能力
最近武汉的n-Cov使得大家只能在家办公了. 在家里的感受是什么样的呢? 1.上班的时候一直在奔跑,现在总算可以有集中的时间来思考一些之前一直没能好好整理的内容 2.时间变得自己可以掌控,优先级有自己 ...
- Java基础语法<十二> 泛型程序设计
1 意义 泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用. 常见应用 : ArrayList 2 K T V E ? object等的含义 类型变量使用大写形式 E – Element ( ...
- Java核心技术第八章——泛型程序设计(1)
1.泛型程序设计 泛型程序设计意味着编写的代码可以被很多不同类型的对象所重用.例如:不希望为了聚集String和Integer对象分别设计不同的类.(个人觉得此处说的聚集译为:创建一个对象,属性可以为 ...
- Java核心技术卷一基础知识-第12章-泛型程序设计-读书笔记
第12章 泛型程序设计 本章内容: * 为什么要使用泛型程序设计 * 定义简单泛型类 * 泛型方法 * 类型变量的限定 * 泛型代码和虚拟机 * 约束与局限性 * 泛型类型的继承规则 * 通配符类型 ...
- c/c++ 通用的(泛型)算法 之 只读算法,写算法,排序算法
通用的(泛型)算法 之 只读算法,写算法,排序算法 只读算法: 函数名 功能描述 accumulate 求容器里元素的和 equal 比较2个容器里的元素 写算法 函数名 功能描述 fill 用给定值 ...
- c/c++ 通用的(泛型)算法 generic algorithm 总览
通用的(泛型)算法 generic algorithm 总览 特性: 1,标准库的顺序容器定义了很少的操作,比如添加,删除等. 2,问题:其实还有很多操作,比如排序,查找特定的元素,替换或删除一个特定 ...
随机推荐
- sweetalert2 全面替代 alert ,从 sweetalert2 弹出 text 到 弹出 Dom 以及模态框和取消 sweetalert2 的 OK 按钮
1. 简易基本版 sweetalert 涵盖日常基本的弹出及对话框 2. 升级版本 sweetalert2 满足常见开发工作中的各种要求 3 取消 OK 按钮, 只需要设置 showConfirmBu ...
- BZOJ 3203 Luogu P3299 [SDOI2013]保护出题人 (凸包、斜率优化、二分)
惊了,我怎么这么菜啊.. 题目链接: (bzoj)https://www.lydsy.com/JudgeOnline/problem.php?id=3203 (luogu)https://www.lu ...
- Elasticsear搭建
2.1:创建用户: (elasticsearch不能使用root用户) useradd angelpasswd angel 2.2:解压安装包 tar -zxvf elasticsearch-5.5. ...
- css中如何使用border属性与display属性
border属性介绍 border属性设置元素边框. 边框3个要素如:粗细.线型.颜色. 边框线型属性值说明表如: 属性指 描述 none 定义无边框. hidden 与 "none&quo ...
- 一台linux机器远程mount另一台linux机器
本机电脑系统是unbantu,要将另一台linux电脑上的文件mount到本机目录下.mount的原理是网络文件系统,即NFS,本机操作步骤如下 一,安装 nfs-common : apt inst ...
- express 请求参数的一些问题
先说点别的,项目入口是index.js,运行 node index 启动项目. 路由部分app.get('/', function(req, res) { res.send('hello, expre ...
- Type.MakeGenericType 方法 (Type[]) 泛型反射
替代由当前泛型类型定义的类型参数组成的类型数组的元素,并返回表示结果构造类型的 Type 对象. 命名空间: System程序集: mscorlib(mscorlib.dll 中) public ...
- MySQL——执行计划
项目开发中,性能是我们比较关注的问题,特别是数据库的性能:作为一个开发,经常和SQL语句打交道,想要写出合格的SQL语句,我们需要了解SQL语句在数据库中是如何扫描表.如何使用索引的: MySQL提供 ...
- leetcode 138. Copy List with Random Pointer复杂链表的复制
python代码如下: # Definition for singly-linked list with a random pointer. # class RandomListNode(object ...
- 前端必须掌握的 docker 技能(1)
概述 作为一个前端,我觉得必须要学会使用 docker 干下面几件事: 部署前端应用 部署 nginx 给部署的 nginx 加上 https 使用 docker compose 进行部署 给 ngi ...