返回首页

简介
使用集合在大多数情况下,需要遍历集合,做了计算,并收集在一个变量的结果,经常出现。本文给出了一个简单的方法,这在C,最常见的方法不同,使用表达式模板的容器一起。本文将使用STL,但该技术可以应用到任何容器。常用的方法
在集合迭代最常用的方法是使用一个for循环。一段时间后,for循环的写作变得繁琐,因此许多语言提供了一个"每个'语句,允许在集合的迭代。而C不提供这样一个说法,这是很容易以各种方式来实现它。最常用的方法是在一个函数接受回调,这样的循环:模板LT;类CGT;无效的forEach(C放大器,C, & #160; 无效(*回调)(C::value_type的)){ 用于(C:迭代= c.begin();  0; = c.end()){ 回调(*); }}
但是,这种方法有一些缺点,它的中断,使他/她认为关于在何处放置回调程序员的思维过程,以及如何从里面的回调访问本地数据。表达式模板
表达式模板来作为救援:使用运算符重载,表示绑定本地参数表达式的类,可作为回调为每个循环。在解释如何编写这样的类,让我们来看看使用的一个例子:#包括LT; listgt;#包括LT; iostreamgt;使用命名空间std;主要INT(){ listlt; intgt; L;  60; l.push_back(1); l.push_back(2);   ; l.push_back(3); INT I = 0; & #160; Exprlt; INT GT,X; 的forEach(L,I,X = I);  60; 法院LT,LT,X; getchar函数(); 返回0;}
正如你可以看到,这是很容易总结使用上面的代码中的号码清单!它是如何工作
这里是重要的代码行,让我们的重点放在结构foreach(L,I,X = I);
C并没有lambda函数或关闭,但它的操作符重载。所以在上面的代码,x是一个对象=操作符适用于它时,它实际上没有任何补充,但它会创建一个函数对象,封装变量x和我,调用时,它将执行的行动。
类EXPR x是一个实例是:模板LT类TGT;类Expr之间{市民: Expr之间的():m_v(T(下)){ & #160; } ExprAddAssignlt; TGT;运算符=(T&I){ 60; 返回ExprAddAssignlt; TGT;(m_v I); & #160; } 运营商T()const的{ & #160; 返回m_v; } 私人:  0;T m_v;
我们可以看到,它封装了一个T类型的值,我们也看到,运营商=返回ExprAddAssign类,这是这个类的一个实例:模板LT;类TGT;类ExprAddAssign {市民: ExprAddAssign(T放大器; LV,常量T放大器; RV):  60; m_lv(LV),m_rv(RV){ }  ; void运算符()()const的{   ; m_lv = m_rv; }私人: T放大器; m_lv; 常量T放大器; m_rv;};
上面的类包含两个绑定:一个右值左值之一。左值分配rvalue的价值。的功能"的forEach"代码变为:模板LT; T类,C类,类FGT; 无效的forEach(const的彗星放大器,C,T&,V,F放大器; OBJ){ (C:为const_iterator = c.begin(); &# 160; = c.end()){ V = *;& #160; OBJ(); }}结论
各种各样的表达式模板进行编程。即使结构像IF - THEN - ELSE可以使用像一个Smalltalk语法编码。例如:的forEach(L,(I GT; 2)ifTrue(X = I));
其实我意外地来到了这个解决方案,寻找一种方法,使lambda函数在C。我意识到,一个并不需要的lambda函数,只要为lambda参数可以声明为局部变量。
我觉得很奇怪,STL库不包含这样一组类。它提供了极大的权力为C ... ...

回答

评论会员:斯蒂芬休伊特 时间:2011/12/06
你应该看看]库。

史蒂夫
评论会员:斯图尔特Dootson 时间:2011/12/06
太令人吃惊多久我请参阅一个在CP有趣的文章标题,有一个快速寻找并认为"我敢打赌有建议在升压"{S0}
评论会员:游客 时间:2011/12/06
斯蒂芬休伊特的注释|呀。但升压包含了很多很酷前沿的东西。我觉得有点惊人,你多久读取代码项目的文章,并发现有人提出了Boost提供一个自由工业实力版的土布版本。这并不意味着作为这篇文章的批评呢??我只有在它表面看??但是基础上,(我自己也承认浅)考试,它看起来像很多Boost.Lambda。史蒂夫
Achilleas Margaritis
评论会员:游客 时间:2011/12/06
其实我的文章一个不同风格的lambda比提高。我特别喜欢的升压方法的"占位符变量","绑定"等,原因是不是:1)代码看起来更好,没有丑"_1","_2"等,经过一段时间,这是不容易阅读。2)升压的方法是很难新手(到C新手,新手提高)。我可以用"_1"和"X"作为占位符,但旁边的人被分配到该项目,否则可能会混淆。3)使用占位符变量可能有意外的副作用。例如,代码"法院LT,LT;_1LT,LT;1"代码"法院LT,LT;1LT,LT;_1"的执行有很大不同,虽然它们看起来特别是类似。
斯蒂芬休伊特
评论会员:游客 时间:2011/12/06
。如果占位符的名称使用Bo​​ost.Lambda时得罪你,你可以添加自己的你会怎么做这样的事情,用你的系统?codeprespanclass="code-keyword"typedef/spanvectorspanclass="code-keyword"</spanspanclass="code-keyword"int/spanspanclass="code-keyword">/spanInts;Intsi1,i2,o;spanclass="code-comment"///spanspanclass="code-comment"Codeherewhichfills"i1"and"i2"withnumbers./spantransform(i1.begin(),i1.end(),i2.begin(),back_inserter(o),_1+_2);/pre/code填写此代码加入相应的值从"I1"和"I2"载体"O"。实际Lambda表达式"_1_2"简洁的占位符添加的清晰度,而再减去它。史蒂夫
Achilleas Margaritis
评论会员:游客 时间:2011/12/06
我会做这样的:{C}
斯蒂芬休伊特
评论会员:游客 时间:2011/12/06
你已经改造多个轮子在这里:-您使用的纺的for_each家版本,这是一个标准的STL算法。您所使用版本的forEach,没有被定义的任何地方,但它看起来像,如果写的,想STL算法变换。-您可以使用back_inserter家纺版本,这是一个标准的STL迭代。您还引入两个局部变量。是否引进所有这些新的结构实际上是想为"菜鸟"容易吗?它将使"oldbie的"更难。鉴于许多Boost库,使之成为它的下一个版本的STL,你还可以运行重塑STL的,而不是扩充它非常真实的风险。史蒂夫
Achilleas Margaritis
评论会员:游客 时间:2011/12/06
嘿,放松{S0},我只是传达一些想法。我个人不采取STL/升压为"一个真实的方式"做事。请允许一些分歧!
斯蒂芬休伊特
评论会员:游客 时间:2011/12/06
我放松-也许你应该(放松),它听起来像你解释作为攻击我的意见。文章和替代方法表达意见,是在每篇文章的末尾留言板是什么。我会认为你的文章没有完成,但没有提Boost.Lamda,现在我已经纠正,CP的读者。史蒂夫
Achilleas Margaritis
评论会员:游客 时间:2011/12/06
也有功能界别的读者希望进一步调查这起。
ikolev
评论会员:游客 时间:2011/12/06
有很多人拒绝使用升压LAMBDA,MPL,以及其他一些原因,特别是较重的库。他们更喜欢简单的方法,例如在这篇文章中所描述的。有时,他们甚至从升压翻录一些简单而优雅的解决方案,以避免吨的依赖,它会招致如果直接使用。具体到升压LAMBDA,我想引述最近comp.lang.c后主持:"我不会用[升压Lambda和凤凰城]在生产代码。例如,我真的不希望看到在调用栈Boost.Lambda表达,当我在寻找一个生产问题的核心转储。任何重要的Boost.Lambda表达式的语法仅仅是不可读(现有的彗星构造,因为它引入了一个新的语法),更不用提,编译后的代码是狗缓慢的,如果内联被禁用。"所以我觉得类似这样的"重塑"的东西,在升压或其他地方,在一个简单的方法做的文章随时欢迎,只要他们提到现有的替代解决方案,并比较所有方法(DIS)的优势。
斯蒂芬休伊特
评论会员:游客 时间:2011/12/06
在Boost.Lamda:我只会使用非常简单的功能Boost.Lambda。如果你必须写一个复杂的lambda函数,它几乎肯定会得到更好的而不是写一个函数或函数对象。这就是说STL的问题之一是,代码往往成为散落100S与琐碎的函数对象-这是我认为Boost.Lamda是理想的解决问题。牢记,做正确的语言将需要延长的lambda函数(实际上已建议)。我对这篇文章这样-但我没有觉得有必要提成熟的替代品,我知道(Boost.Lamba) 史蒂夫
杰里耶利米
评论会员:游客 时间:2011/12/06
我只想说一句:我认为提高有很多伟大的东西。我真的很喜欢的提高::精神的语法,虽然我以前没有在推动看着:波长它看起来很酷以及传统上,我从来没有使用升压,只是因为它是如此沉重......一个巨大的库(STL)是不够的。出于这个原因,如果我要使用这样的事情,我可能会推出自己的。所以看到这篇文章真的帮助我澄清在我的脑海,我怎么能做到这一点,它可能看起来像什么。就个人而言,如果我是喜欢这个自己开发的东西,我会尝试使用标准的for_each算法,但是这是一个个人的设计决策。我发现的解决方案,只是因为它是,真正让我的思想和我读这些文章的主要原因(我从来没有实际使用的代码,我发现在CodeProject上...).{BR}我认为这是一个很好的文章。应该提到的提高,因为提高似乎一切需要(在这种情况下,以及真正的!),但不从这篇文章的实用性减损(不适合我反正)。的东西即使这个线程的意见是值得一读。感谢你。杰瑞
斯蒂芬休伊特
评论会员:游客 时间:2011/12/06
杰瑞耶利米写道:传统上,我从来没有使用过的刺激仅仅因为它是如此沉重Boost是不是"重"。显然,这取决于你使用它的小头文件只类的大部分库。STL是不是巨大的。我不知道是什么让你这样的印象。史蒂夫
杰里耶利米
评论会员:游客 时间:2011/12/06
我写的嵌入式软件。我通常有一个"合理"的内存量,但我有我的软件的内存只要2K少。一般图书馆是"全功能"更糟的内存明智的比剥离下来的类,实现准确,所需的功能。所以,它真的取决于你如何定义"重"。STL是不是适用于台式机和服务器应用程序的沉重。试过写不到1MB的内存与它一台机器上的软件吗?据我了解,个别提升功能都依赖于其他件,所以使用只是一个功能,不包括任何Boost库的另一部分是很难。现在,像我之前说的,我都避免使用它,我就可以对这个错误...如果我能适应一个分析器,用于提高:成小于10K的内存的精神,我可能会使用它。增加的基础上提高一个分析器:精神比一个10K的足迹添加一个可执行{了BR}杰里
斯蒂芬休伊特
评论会员:游客 时间:2011/12/06
精神是我不能使用的图书馆之一:我使用的MSVC6,它不工作就可以了。有趣的是,看升压页,看到图书馆工作的编译器-。MSVC的6是很容易的最坏现代普遍使用的编译器仍然我尝试了"BOOST_FOREACH的"一天比较生成的机器码(发布版本)到硬盘的书面循环。令我吃惊的,它实际上是较小。虽然,如果你看一下"BOOST_FOREACH的"背后的代码表面你不会预测这是模板元函数,它们在编译时计算,不利于生成的代码的大小。您可能会同样感到惊讶,如果你给库的一些第二个样子。史蒂夫
杰瑞耶利米
评论会员:游客 时间:2011/12/06
我偶然发现了这篇文章,刚才和阅读。然后认为我应该发表评论。然后,我读的意见,并意识到我已经做到了!我想说,我喜欢这篇文章,因为我想知道这些东西是如何工作的内部和升压源代码,使我的眼睛水。这是CP值有一年,根据我的腰带(但仍使用我的Windows开发的MSVC6)我想说:-我仍然无法弄清楚如何使用自身增强的一个特定的位,因为每一个升压位升压其他位上的依赖关系。-我使用了错误的编译器-我什至不能写我自己的东西,因为编译器是如此的不合标准的。显然,新版本的更好。如果我得到一个新的编译器的升压或POCO的肯定我会用的东西。但我仍然喜欢这样的文章,因为我需要知道它是如何在里面。你不能这样做不理解代码不正是嵌入式开发。不幸的是,这已我希望从我的Windows开发,以及也许你不会使用此代码,在偏好的升压东西,但使用它作为一个学习工具,是我加入CP的原因。作者应该提到相当于functionaliy,升压,然后解释他为什么喜欢他的版本。这最有帮助的,但不会大幅偏离的效用,我从阅读的文章。杰瑞
基思农民
评论会员:游客 时间:2011/12/06
有一些老乡C用户(​​C/CLI,实际上)将高兴地看到可以完全充实到支持的DLinq表达式树imgsrc=http://www.orcode.com/upimg/2011_12_06_08_39_11_1.gif-----{BR}祁彦辉农民[MSFT:VC#/的DLinq]