Python 的 yield 在 C++ 上的一种实现
来源:互联网 发布:中国移动积分兑换软件 编辑:程序博客网 时间:2024/06/11 04:44
Python 上的 yield 是很令人着迷的语句,其简洁强大充分体现了面向对象的优点。Python 把带有 yield 的函数认为是 “产生生成器的函数”。在我看来,生成器的意义就是,隔离开了值的 “产生” 与 “消耗” 的代码。
很多人试图在 C++ 中实现 yield 语义,比如 boost 就有一种实现。这些实现大抵都是,利用 C++ 的 switch 语句,以 __LINE__ 宏为标签,实现跳转的效果——但我觉得,这背离了生成器原本的意义。
我也实现了 yield 语义,并且也把带有 yield 语义的对象定义为生成器。代码详见https://github.com/JazzLeee/Generator-in-C-
这里演示一下生成器用法,因为程序用到了 C++1y,并且该标准在不同编译器上的实现不一致,我是用 vs2015 编译通过的。
作为例子, 我用生成器实现了一个 Unicode 的解码/编码工具,包含在 acgt/acgt_g_unicode.h 中,下面的代码描述了,如何打开用 utf8/utf16le/utf16be/utf32le/utf32be 编码的文本 unicode.txt:
#include <iostream>#include <acgt/acgt_g_unicode.h>using namespace acgt;int main() { std::wcout.imbue(std::locale("chs")); // 函数 utfText 返回一个生成器 // 可用 operator| 传给该生成器 函数/仿函数/匿名函数 utfText("unicode.txt") | [](wchar_t c) { std::wcout << c; }; return 0;}
或者说,你想打开 unicode.txt 之后,用 utf8 格式保存,可以这样做
#include <fstream>#include <acgt/acgt_g_unicode.h>using namespace acgt;int main() { std::ofstream file("utf8.txt", std::ios_base::binary); // wgener 用于那些编写为“接受一个生成器作为参数”的生成器 // utfText("unicode.txt") 作为生成器传递给了 // wgener<WG_ucs4_to_utf8_with_BOM> 这个生成器 wgener<WG_ucs4_to_utf8_with_BOM>(utfText("unicode.txt")) | [&](char c) { file.write(&c, 1); }; return 0;}
下面,演示如何编写一个质数生成器
#include <iostream>#include <cmath>// 生成器模板位于 acgt/acgt_generator.h 中#include <acgt/acgt_generator.h>using namespace acgt;// 首先,写一个判断质数的谓词bool is_prime(unsigned n) { for (unsigned i = 2; i <= std::sqrt(n); i++) if (n % i == 0) return false; return true;}// 然后,编写一个质数生成器// 任何生成器都是一个 只有一个模板参数T 的模板// 继承于 Generator<T, 参数类型列表>template < typename T> struct G_Prime : Generator<T, unsigned> { // 需要用 GInit 来继承父类的构造函数 GInit; // 然后编写生成器本体,接受参数 n,生成不大于 n 的质数 // 生成器本体是一个 void body(形参列表) const 函数 // 因为需要覆盖父类的函数,所以推荐用 override 检查 void body( unsigned n ) const override { for (unsigned i = 2; i <= n; i++) if (is_prime(i)) yield(i); }};int main() { // 使用 gener 函数来驱动一个生成器工作 gener<G_Prime>(100) | [](unsigned n) { // 打印质数 std::cout << n << ' '; }; std::cout << std::endl; return 0;}
这样的生成器才真真正正起到了隔离值的 生成 和 消耗,实现了更好的面向对象。
我还提供了一些操作,让传给生成器的函数,能够初步控制生成器的行为。
比方说,你可以用 GExit 指令让生成器无条件退出,也可以用 GReset 指令让生成器无条件重启,并且在嵌套生成器中也不会出现问题。
//...... utfText("unicode.txt") | [](wchar_t c) { if (c == L'#') GExit; std::wcout << c; }; //......
暂时先写到这里,对生成器有兴趣的朋友可以添加联系。
QQ: 390855044
- Python 的 yield 在 C++ 上的一种实现
- Python的yield关键字
- Python的yield关键字
- python yield的用法
- Python的yield用法
- Python yield的使用方法
- Python的yield
- python的yield使用
- python的yield使用
- Python yield 的理解
- Python的yield
- python调用c语言函数的一种简单实现方法
- 《Python-yield的简单练习》---yield实现单线程下的并行
- 总算在C#.NET,Python,Ruby上实现了php的zlib的gzcompress函数
- python yield 另外一种用法
- Python的yield协程机制实现生产者-消费者模式
- 关于实现在阿里的Antd的Modal上实现动态表的一种思路
- Python中yield的用法
- scp指令
- 如何在使用moveRowAtIndexPath:方法时替换默认图片
- java下载文件名乱码
- Android 自定义软键盘
- Java—内部类(三)—内部类的继承
- Python 的 yield 在 C++ 上的一种实现
- 《Unity_API解析》 第三章 GameObject类
- android应用版本升级时签名冲突问题的原因及解决办法
- 数据结构学习笔记(前言)
- PhalApi框架浅谈之融云扩展类库(PhalApi——RongYun)
- CRAN 的任务视图(View Task)
- linux常见命令
- Linux下NFS的配置
- Android 6.0 sensor 框架详解(前言)