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,问题:其实还有很多操作,比如排序,查找特定的元素,替换或删除一个特定 ...
随机推荐
- C++ -- 类与成员
一.初始化列表 1.是构造函数中一种成员的初始化方式 例如,class 类名 { 类名(参数列表):成员1(成员1),成员2(成员2)... { } } 2.用此方法可以解决类中的成员与 ...
- 在Sublime Text 3中配置Python3的开发环境/Build System
本文来源:https://www.cnblogs.com/zhangqinwei/p/6886600.html Sublime Text作为一款支持多种编程语言的文本编辑神器,深受广大开发者的喜爱.通 ...
- sqli-labs(31)
0x01找闭合 这里是WAF的jsp调到php的同样 第二个参数构造 偷看源码 闭合是") 我们尝试一下构造爆破数据库名 login.php?id=&id=-") unio ...
- 误用 Kotlin 中的 sortedWith() 方法排序,集合没有变化
时间:2019年8月4日14:17:06问题描述:看下边的小例子: data class Man(val name: String, val age: Int, val type: Int) fun ...
- ffplay播放YUV数据
播放器YUV系列的格式用ffplay很方便 免费的 播放NV21 ffplay -i d:/cap.yuv -pix_fmt nv21 -s 640x480 播放YUV420P ffplay -i d ...
- 如何让你的JS代码写的更漂亮
感觉这篇文章总结的js的规范写法不错,拿来收藏.转自:https://mp.weixin.qq.com/s/AtR94IL9BW9EXOTnKOilmA 1. 按强类型风格写代码 JS是弱类型的,但是 ...
- C# 格式化XML方法
/// <summary> /// 格式化XML方法 /// </summary> public class UXMLFormat { public static string ...
- C语言字符数组详解
字符串的存储方式有字符数组和字符指针,我们先来看看字符数组. 因为字符串是由多个字符组成的序列,所以要想存储一个字符串,可以先把它拆成一个个字符,然后分别对这些字符进行存储,即通过字符数组存储.字符数 ...
- C++/C# 转化 Marshal VS Ptr
Vidyo32.VidyoClientInEventLogin Login = new Vidyo32.VidyoClientInEventLogin(); Login.portalUri = thi ...
- Service层获取HttpServletRequest request
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/liuyunshengsir/article/details/78183058HttpServletR ...