C++09的lambda expression,加上RAII,将会带来一个可用性极强的scope(exit)设施

98 views
Skip to first unread message

pongba

unread,
Sep 24, 2007, 9:46:02 AM9/24/07
to pon...@googlegroups.com
瞧这个:

class ScopeExit
{
public:
ScopeExit(tr1::function<void()> func) : func_(func) { }
~ScopeExit() { func_(); }
private:
tr1::function<void()> func_;
};

#define BOOST_SCOPE_EXIT(expr) \
  ScopeExit scope_exit_##__LINE__(expr)

// use case
void f()
{
bool commit = false;
account1.draw(10);
BOOST_SCOPE_EXIT((
  <&>(){
    if(!commit)
      account1.deposit(10);
  }
));
account2.deposit(10);
commit = true;
}

接近完美了:-) 什么都不依赖。除了使用的时候要把lambda expression用一个额外的()括起来:)

--
刘未鹏(pongba)|C++的罗浮宫
http://blog.csdn.net/pongba
TopLanguage
http://groups.google.com/group/pongba

red...@gmail.com

unread,
Sep 24, 2007, 9:50:47 AM9/24/07
to pon...@googlegroups.com
我还是喜欢 D 那种, 常用的设施, 直接用语言实现的做法, 看起来简单清爽, 写起来出了错容易查找, 不至于无谓浪费时间.

不过呢, C++ 0x 也算大有进步了, 隔了11 年了.


pongba 写道:

Atry

unread,
Sep 24, 2007, 1:13:33 PM9/24/07
to pon...@googlegroups.com
用抹去类型的函数对象可能有额外的堆内存分配,开销太大了。即使有小缓冲区优化也要初始化复制很多东西,而且编译器很难内联。最好用模板参数的函数对象。

template<typename Function>
class ScopeExit
{
public:
ScopeExit(Function const & func) : func_(func) { }
~ScopeExit() { func_(); }
private:
Function func_;
};
template<typename Function>
ScopeExit<Function> make_scope_exit(Function const & func) {
 return ScopeExit<Function>(func);
}


#define BOOST_SCOPE_EXIT(expr) \
  auto scope_exit_##__LINE__ = make_scope_exit(expr)

在07-9-24,pongba <pon...@gmail.com> 写道:

Atry

unread,
Sep 24, 2007, 1:16:32 PM9/24/07
to pon...@googlegroups.com
我这个代码不对,我那样还得加上 move 语义了。
最好把宏定义改成这样:

#define BOOST_SCOPE_EXIT(expr) \
ScopeExit<typeof(expr)> scope_exit_##__LINE__(expr)


在07-9-25, Atry <pop....@gmail.com> 写道:

Huafeng Mo

unread,
Sep 24, 2007, 9:20:53 PM9/24/07
to pon...@googlegroups.com
问题都有两面性,语言内置的实现,更加简洁和直接。但是语言每增加一种设施,便可能增加未来扩展的障碍。通过库实现语言扩展,就目前而言,都显得很丑陋,但对于语言未来的扩展也少很多障碍。
这完全取决于语言设计的理念。
完全通过内置机制实现语言特性的语言,通常是面向当前的。众多功能性的特性已经将语言圈定在一个狭窄的范围内。
通过建立基础特性,然后利用基础特性组合获得新特性的语言,通常是面向未来的。因为没有很多特性作为发展的障碍。
以C++的lambda为例,C++没有lambda,但牛人们利用gp和tmp模拟了lambda,姑且应付。但发现不好用,随后在语言扩展的时候再加入。如果一开始就加入,那么万一设计有问题,那么永远也没翻身机会了。而通过模拟运用之后,可能的问题基本上也发现了,届时的语言机制也成熟了。
我更喜欢更有发展余地的语言,我是个乐观主义者。:-)
当然,最好是哪个天牛(天才牛人:-))能够发明一种语言,只包含最基础的语言设施,而通过库创造出来的语言新特性能像内置特性一样,这就最完美了。

red...@gmail.com

unread,
Sep 24, 2007, 9:54:51 PM9/24/07
to pon...@googlegroups.com
一个重要的功能, 而且可能会得到广泛使用的功能, 开初就需要好好设计, 否则无
法是通过语言的方式来实现, 还是通过库的方式来实现, 一旦广泛使用之后, 要改
的代价都非常高, 用库不见得比用语言的代价更低.

iostream 设计得不是很好, 似乎部分大师级人物也有此认识, 但是我们能够摆脱
得掉吗? 不少 C++ 的库已经依赖于它了; 还有很多人让asio 的作者在 asio 中对
iostream 进行支持.

不过这个不是更重要的, 更重要的是, 语言应该更积极地进化. 语言应该帮助用户
减轻脑力负担, 而不是号称可减轻负担, 但从左边减轻3点负担, 又从右边引入4点
负担.

我更喜欢分版本的语言, 例如 Java, C#, Python等, 好处是, 你的程序尚不支持
新版本的时候, 可以继续沿用旧版本, 而新版本可以做出更多的变化, 可以引入一
些不兼容的变化; 大家有时间判断要不要升级, 要升级要做什么准备. 特别是
Python, 很多计划早早就提出来充分讨论, 同时多个版本并行支持很久.

C++ 呢? BJ 说不喜欢分裂, 如此同时, 演进速度如此之慢, 让人太过失望.

这个世界上, 不变而且不需要变的东西, 是已经死亡的东西. 虽然说 C++ 语言能
力强, 用库可以实现很多东西, 但是, 用库代替语言实现本该语言实现的许多功
能, 那里面带来多少垃圾东西? 轻则是不方便, 重则一团浆糊, 出了错都不知道死
在哪里.

虽然偶尔动动脑力体操是很好的, 但是用C++ 工作, 经年累月都要小心翼翼, 每次
写一个类的时候, 要防止copy, 防止 assignment, 构造的时候异常怎么办等等等
等, 还要和vc, gcc(还好我不用 icc) 不同的特性做斗争, 看古怪到摸不着头脑的
出错信息, 真是受够了.

C++ 是伟大的语言, 做了很多探索, 得到了很多成就, 别的语言从它那里借鉴了许
多, 但是它自己就像一个包袱其重又什么都不舍得放弃的大笨熊, 走都走不动.

我现在喜欢看 C++ 的进展, 看看它带来的新思想, 但是我已经不愿意使用它了.

Huafeng Mo 写道:
> 问题都有两面性,语言内置的实现,更加简洁和直接。但是语言每增加一种设
> 施,便可能增加未来扩展的障碍。通过库实现语言扩展,就目前而言,都显得很
> 丑陋,但对于语言未来的扩展也少很多障碍。
> 这完全取决于语言设计的理念。
> 完全通过内置机制实现语言特性的语言,通常是面向当前的。众多功能性的特性
> 已经将语言圈定在一个狭窄的范围内。
> 通过建立基础特性,然后利用基础特性组合获得新特性的语言,通常是面向未来
> 的。因为没有很多特性作为发展的障碍。
> 以C++的lambda为例,C++没有lambda,但牛人们利用gp和tmp模拟了lambda,姑
> 且应付。但发现不好用,随后在语言扩展的时候再加入。如果一开始就加入,那
> 么万一设计有问题,那么永远也没翻身机会了。而通过模拟运用之后,可能的问

oldrev

unread,
Sep 24, 2007, 11:05:08 PM9/24/07
to pon...@googlegroups.com

这没什么难的,不就是开放编译器接口么?我以前提过的 Nemerle 语言就有这样的能力。当然,一门允许完全自定义语法的语言会将任何随机的数据都接受为合法的程
序,很难说这是好还是坏。

简洁是对的,但是不能过渡,这就是为什么我们有了 for 还需要 do/while 的原因。

oldrev <oldrev(at)gmail(dot)com>
Regards

>>> 引用的文字:


On Tuesday 25 September 2007 09:20:53 Huafeng Mo wrote:
> 问题都有两面性,语言内置的实现,更加简洁和直接。但是语言每增加一种设施,便可能增加未来扩展的障碍。通过库实现语言扩展,就目前而言,都显得很丑陋,但对于

>语言未来的扩展也少很多障碍。 这完全取决于语言设计的理念。

Huafeng Mo

unread,
Sep 24, 2007, 11:06:01 PM9/24/07
to pon...@googlegroups.com
一个重要的功能, 而且可能会得到广泛使用的功能, 开初就需要好好设计, 否则无
法是通过语言的方式来实现, 还是通过库的方式来实现, 一旦广泛使用之后, 要改
的代价都非常高, 用库不见得比用语言的代价更低.
===========================
有谁能保证一开始就能设计好呢?特别是那些处于探索阶段的新兴特性?
关于兼容性,我上半年就遇到一个。我为公司做了一个基础组件,当时用了vc8。但是有一个项目要用我的组件。但他是个老项目,用的是C#2003。结果无法引用我的组件。我提议他升级到2005,得到的答复是,需要大范围修改。于是,我做雷锋, 把代码移植回vc7.1。谁让我的东西小呢。然后,夏天的时候,那个项目升级了,到C#2005。这回我想该没事了吧,结果用我的组件没问题,但是,需要同时安装.net2.0和.net1.1。这下客服跳起来了,软件才10来M,这两个东西一装,至少1个小时。要我们少装一个。也只有我做牺牲,老的vc8代码是不能用了,算法已经改过了。再移植一个吧。此后,我就把兼容性和延续性贡上了香案。
对于程序员而言,这种事情没什么大不了的,无论是开发,还是移植,都一样那工钱。对于企业而言,损失的就是白花花的利润。嗨,碰巧我还是一个爱财如命的小股东。:-(
C++在库扩展语言方面迈出了第一步,某些方面成功了,比如像内置类型一样处理用户定义类型,其结果已为很多语言所用;另一些方面失败了,比如lambda。无论成功还是失败,都指出了一个方向,为后人铺平道路。咱们也别把话说死嘛。
C++的一些基础性缺陷,很大程度上是可能修复的,众牛人们正在为此努力。比如,对于持有资源的非平凡类的默认复制,已经有一些不破坏兼容性的解决方案。其实,在马路上开车压死个把人,要比在C++里犯错容易多了。呵呵,我说过,我是个乐观主义者。


在07-9-25,red...@gmail.com <red...@gmail.com> 写道:

pongba

unread,
Sep 24, 2007, 11:09:16 PM9/24/07
to pon...@googlegroups.com
没错。一旦开放编译器接口,允许自定义语法。就会出现各种各样千奇百怪的DSL,用的时候等于学习新语言。而且,这其实相当于打开了潘朵拉的盒子。Eric Raymond不是也说过么,程序员(人们)会仅仅因为能够那么做而就去做了..

Huafeng Mo

unread,
Sep 24, 2007, 11:19:32 PM9/24/07
to pon...@googlegroups.com
当然要确保语言的安全和稳定。否则,汇编就能达到这种标准。我说不清我的想法。举个例子,模板表达式,迟后计算是C++不支持的,但通过一些看似无关的语言机制,组合起来,使得C++可以实现这种计算。
差不多就是这个意思。
boost::lambda接近了这种情况,但是受限于所用的语法机制,无法达到应用的效果。或许因为C++的基础语法设施还不够本质?还不够"几于道矣"?瞎猜猜。

在07-9-25,oldrev <old...@gmail.com> 写道:

red...@gmail.com

unread,
Sep 24, 2007, 11:23:23 PM9/24/07
to pon...@googlegroups.com
Huafeng Mo 写道:

> 一个重要的功能, 而且可能会得到广泛使用的功能, 开初就需要好好设计, 否则无
> 法是通过语言的方式来实现, 还是通过库的方式来实现, 一旦广泛使用之后, 要改
> 的代价都非常高, 用库不见得比用语言的代价更低.
> ===========================
> 有谁能保证一开始就能设计好呢?特别是那些处于探索阶段的新兴特性?

那, 宁愿什么功能都等个10年8年, 什么都看明白了, 才推出好呢, 还是采用多语
言版本, 象 Java 那样, JDK 1.2, 1.3, 1.4, 1.5, 先推一个尽量好的, 运气不
好, 发现有问题, 下一版本再改改呢 ? 我就宁愿后者.

现在内存大大便宜了, 说老实话, 如果 D 不出来, 可能我就要转到 C + Java 上
了. C 之所以抛不开, 因为我还要写 linux kernel module.


当然, 要让用户在互联网上下载的程序, 有些特殊的考虑, 这里有另外一些考虑
(如果程序很小, 我宁愿用 delphi 7 写, 如果程序不是太小, 那么方法多了,
Delphi, C++/Python, C++/lua 等都方法都可以.)

Huafeng Mo

unread,
Sep 24, 2007, 11:33:32 PM9/24/07
to pon...@googlegroups.com
对于成熟特性,这没什么或说的。可对于特性呢?
Java依仗身后的财主可以随便改,可苦了企业了,当然还有股东。:-)

在07-9-25,red...@gmail.com < red...@gmail.com> 写道:

Huafeng Mo

unread,
Sep 24, 2007, 11:35:30 PM9/24/07
to pon...@googlegroups.com
写错了:
对于成熟特性,这没什么或说的。可对于新特性呢?
Java依仗身后的财主可以随便改,可苦了企业了,当然还有股东
。:-)


在07-9-25,Huafeng Mo < longsh...@gmail.com> 写道:



--
反者道之动,弱者道之用

red...@gmail.com

unread,
Sep 24, 2007, 11:36:48 PM9/24/07
to pon...@googlegroups.com
嗯, 你的意思是历史积累才让人继续用 C++ ? 

我们现在的情况是, C++ 上面有一些积累, 但是不足让人无视 C++ 的麻烦 --- 光一个 boost.python 就让新人要学习相当时间了,
所以, 决定抛弃积累了.


Huafeng Mo 写道:
对于成熟特性,这没什么或说的。可对于特性呢?
Java依仗身后的财主可以随便改,可苦了企业了,当然还有股东。:-)
---~----~------~----~------~--~---


red...@gmail.com

unread,
Sep 24, 2007, 11:44:50 PM9/24/07
to pon...@googlegroups.com
Huafeng Mo 写道:

> 写错了:
> 对于成熟特性,这没什么或说的。可对于新特性呢?
> Java依仗身后的财主可以随便改,可苦了企业了,当然还有股东
> 。:-)
而且, 企业要保守些, 可以不必追新版本啊, 就想 python 一样, 企业用户升级速
度是很慢的, 但是提供商继续提供支持. python 后面也没有大财团的.

yq chen

unread,
Sep 25, 2007, 12:04:35 AM9/25/07
to pon...@googlegroups.com
呵呵,我感觉VC6.0 和VC2003就是分版本的。不过C++新标准出来后等开发商广泛支持,不知道又到猴年马月了。

对于很多新特性,只能眼馋的份了,一方面希望新标准快出来,一方面又希望编译器厂商先把已经初步定论的东西先支持起来。

谁知道Herb Sutter的团队对新标准一点儿也不积极。

不过还是比较统一redsea的观点,我希望起码在标准库的问题上,应该步伐大一点。先把一些适用的东西搞进去,不行了在废弃就成了。如果在库的扩展上都像语言的扩展上那么束手束脚的,那么C++只会让人期待和失望了。

在07-9-25,red...@gmail.com <red...@gmail.com> 写道:

Huafeng Mo

unread,
Sep 25, 2007, 12:18:08 AM9/25/07
to pon...@googlegroups.com
这个么,呵呵,我没词儿了,我投降,我投降。;-)
回到主题,如果有一个scope需要反复使用,我希望直接封装成一个类型,便于在函数中定义使用。但我又想利用lambda和预制的RAII框架类,来组装这个类型,该怎么做呢?


在07-9-25,yq chen < mephist...@gmail.com> 写道:



--
反者道之动,弱者道之用

Huafeng Mo

unread,
Sep 25, 2007, 2:10:21 AM9/25/07
to pon...@googlegroups.com
我试着这么做:
class MyScope
{
public:
    MyScope():m_scope(<&>(){
         if(!commit)
            account1.deposit(10);
         }) {}
private:
    ScopeExit m_scope;
};
使用的时候就是:

void f()
{
   bool commit = false;
   account1.draw(10);
   MyScope();
   account2.deposit (10);
   commit = true;
}
可是commit怎么办呢?
继续想。


在07-9-25,Huafeng Mo <longsh...@gmail.com > 写道:
这个么,呵呵,我没词儿了,我投降,我投降。;-)



--
反者道之动,弱者道之用
Reply all
Reply to author
Forward
0 new messages