Topic: Lambda Expression + RAII = The landscape of exception-safe programming will change in C++09!


Author: pongba <pongba@gmail.com>
Date: Mon, 24 Sep 2007 10:42:00 CST
Raw View
Exception-safe Programming is hard, but a scope(exit) facility like
that of D language can ease the task. Now it is difficult in C++03 to
implement a easy to use one (http://194.6.223.221/~nasonov/
scope_exit-0.04/libs/scope_exit/doc/html/index.html).

With C++09 coming, we can except that a much more elegant solution is
on the horizon!

Check the code below:

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);
  }
)); // lambda expression - see proposal N2413
account2.deposit(10);
commit = true;
}

Reference:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2413.pdf

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: ymett <ymett.on.usenet@gmail.com>
Date: Mon, 24 Sep 2007 11:24:52 CST
Raw View
On Sep 24, 6:42 pm, pongba <pon...@gmail.com> wrote:
> Exception-safe Programming is hard, but a scope(exit) facility like
> that of D language can ease the task. Now it is difficult in C++03 to
> implement a easy to use one (http://194.6.223.221/~nasonov/
> scope_exit-0.04/libs/scope_exit/doc/html/index.html).
>
> With C++09 coming, we can except that a much more elegant solution is
> on the horizon!
>
> Check the code below:
>
> 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)

The cost of using tr1::function (to be std::function in C++09) can be
avoided:

template<class F>
class ScopeExit
{
public:
   ScopeExit(F func) : func_(func) { }
   ~ScopeExit() { func_(); }
private:
   F func_;
};

template<class F>
ScopeExit<F> make_ScopeExit(F func)
{
   return ScopeExit<F>(func);
}

#define BOOST_SCOPE_EXIT(expr) \
   auto scope_exit_##__LINE__(make_ScopeExit(expr))

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

Usage unchanged.

Yechezkel Mett

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: int19h@gmail.com
Date: Tue, 25 Sep 2007 15:32:59 CST
Raw View
On Sep 24, 8:42 pm, pongba <pon...@gmail.com> wrote:
> Exception-safe Programming is hard, but a scope(exit) facility like
> that of D language can ease the task. Now it is difficult in C++03 to
> implement a easy to use one (http://194.6.223.221/~nasonov/
> scope_exit-0.04/libs/scope_exit/doc/html/index.html).
> With C++09 coming, we can except that a much more elegant solution is
> on the horizon!
>
> Check the code below:
>
> 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);
>   }
> )); // lambda expression - see proposal N2413
> account2.deposit(10);
> commit = true;
>
> }

On a side note, curiously enough, this might be that rare case where
std::uncaught_exception is genuinely useful - it can only be true in
destructor of ScopeExit if the scope in which it was declared did not
complete normally. So:

class ScopeExitSuccess
{
public:
ScopeExitSuccess(tr1::function<void()> func) : func_(func) { }
~ScopeExitSuccess() { if (!std::uncaught_exception()) func_(); }
private:
tr1::function<void()> func_;
};

#define BOOST_SCOPE_EXIT_SUCCESS(expr) \
  ScopeExitSuccess scope_exit_##__LINE__(expr)

void f()
{
  account1.draw(10);
  BOOST_SCOPE_EXIT_SUCCESS((<&>(){
    account1.deposit(10);
  }));
 account2.deposit(10); // throws on failure
}

And then BOOST_SCOPE_EXIT_FAILURE defined similarly.
Also note that the original example was dangerous if deposit can throw
(since the second deposit could then throw from destructor).

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]