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,问题:其实还有很多操作,比如排序,查找特定的元素,替换或删除一个特定 ...
随机推荐
- BZOJ 4897: [Thu Summer Camp2016]成绩单 动态规划
Description 期末考试结束了,班主任L老师要将成绩单分发到每位同学手中.L老师共有n份成绩单,按照编号从1到n的顺序叠 放在桌子上,其中编号为i的成绩单分数为w_i.成绩单是按照批次发放的. ...
- ASP.NET MVC Ajax下载文件(使用NPOI向现有的excel模板文件里面添加数据)
View Html.DevExpress().Button(DevExpressButtonHelper.AddButton(ViewBag.Form, "Export", &qu ...
- SpringCloud 入门知识篇
SpringCloud 入门 springcloud 学习 7天学会springcloud 教程 https://www.cnblogs.com/skyblog/category/738524.htm ...
- python中pip相关命令
用pip安装第三方包的命令 pip install xxx --user 用pip更新第三方包 pip install --upgrade xxx --user 用pip卸载第三方包 pip unin ...
- gitblit 数据迁移(复制)
gitblit 数据迁移 完全拷贝方式: 将原服务器上的gitblit的安装目录.数据目录等相关目录拷到另一台服务器上即可,这样启动方式和使用端口及数据和原服务上的一模一样.(因为gitblit是不用 ...
- 【转】UNITY中相机空间,投影空间的正向问题
原文链接1:https://www.cnblogs.com/wantnon/p/4570188.html 原文链接2:https://www.cnblogs.com/hefee/p/3820610.h ...
- 一个蒟蒻的解题过程记录——洛谷P1003 铺地毯
这到题算是我“火线回归”后码的第一道题,病好了心情不错,发篇博客分享一下 目录: ·题目描述 ·题目分析 ·解题思路 ·代码实现 ·总结 ·题目描述: 为了准备一场特殊的颁奖典礼,组织者在会场的一片矩 ...
- leetcode 240搜索二维矩阵
/** 正常的二维搜索估计要超时,本题沿着对角线搜索,然后找到第一个大于目标数字的坐标(x,y)然后搜索(>x,<y)(<x,>y)子区域: 矩阵size() 为m,n:当i& ...
- 1、Shiro简介以及整体架构
1.Shiro概念和作用: 利用shiro可以快速完成权限管理模块的开发 Spring的官网也是用Shiro做安全管理的... Shiro整体架构: 可能你感觉上面的图片很乱,但是你一定要先大体有个印 ...
- 【ABAP系列】SAP ABAP 行列转换的方法
公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[ABAP系列]SAP ABAP 行列转换的方法 ...