Boost logo

Boost :

From: Hans Larsen (hans_at_[hidden])
Date: 2007-04-03 10:28:59


Hello.

On 1-Apr-07, at 5:38 PM, Alexander Nasonov wrote:

> Hans Larsen wrote:
>> Hello,
>>
>> Better is such a big word. You still have to say in which way it is
>> better; readability, efficiency, simplicity, something else? ;-)
> Readability and simplicity. Compare
>
> std::FILE* f = NULL;
>
> try
> {
> f = std::fopen("/etc/passwd", "r");
> // ...
> }
> finally
> {
> if(f)
> std::fclose(f);
> }
>
> with
>
> std::FILE* f = std::fopen("/etc/passwd", "r");
> scope(exit)
> {
> if(f)
> std::fclose(f);
> }
>
> // ...
>
> Even without D's scope(exit) syntax it looks appealing
>
> std::FILE* f = std::fopen("/etc/passwd", "r");
> BOOST_SCOPE_EXIT(f, (f))
> {
> if(f)
> std::fclose(f);
> } BOOST_SCOPE_EXIT_END(f)
>

Better than finally, yes. I thought you were saying better than my
solution ;-)

>> I admit my solution is not perfect, but it does have certain
>> advantages...
>>
>> First, you seem to use boost/typeof/typeof.hpp, which I failed to
>> find in the boost version I currently use (stable 1.33.1).
> Check it out from cvs or wait for 1.34.

Yes, I figured that out :) I'll need to keep a separate copy of
those if it is really needed...

>
>> I didn't find the documentation in the full doc, only the BoostBook.
> It's not in a distribution but you can generate it or read online at
> http://194.6.223.221/~nasonov/scope_exit-0.02/libs/scope_exit/doc/
> html/
>
>> Why do you need that library and is it absolutely necessary?
> Because I saw so much exception unaware code.

I don't see any case of valid exceptions in the use of this library.
Please point one.

>
>> I don't think it should from the concepts necessary to put the
>> thing together.
>> All you need, after all, is a destructor to call the code, and some
>> variable passing (Boost.Bind is very wonderful).
>
> Bost.Bind and Boost.Lambda are very useful but it's hard to compete
> with
> a plain old C++ code. Try to express the 'if(f) std::fclose(f)', for
> example.

With my code?
        finally f;
        f( if_then( ref(f), bind(std::fclose, ref(f)) ) );

I admit this solution is less readable than yours, but it's still
possible using bind.

>
>> Also, I'm not a big fan of macros, even more when using IDs in them,
>> I think they reduce readability.
> Me too. But this macro can significantly increase a quality of code.
>
>> I prefer compilers to pre- compilers, if you know what i mean.
>> In your case, adding a scope inside the SCOPE_XXX makes for more
>> indentation, which is not necessarily A Good Thingie.
> SCOPE_EXIT, like _if_ or _while_, controls an execution of a code
> block.
>
>> I suggest at least putting those brackets inside the SCOPE_XXX
>> defines.
>> This is all, of course, a matter of taste.
> I personally like brackets because they make a small chuck of code
> surrounded by BIG MACROS more visible. It's also easier to jump
> between brackets (% in vim) and go to the opening bracket([{ in vim).
> But if many people don't like brackets, it's a trivial change ...

Agreed. Although I don't normally use vim, I know it can be useful
(although you could script it ;-).

>
>> BTW, what happens if I typo the ID or just use the
>> same in two different places (either in the same scope or inlined
>> scopes).
>
> Typo:
>
> hello.cpp: In function `int main()':
> hello.cpp:18: error: `boost_scope_exit_struct_typo' was not
> declared in
> this sco
> pe
> hello.cpp:18: error: expected `;' before "const"
> hello.cpp:18: error: `boost_scope_exit_typo' was not declared in this
> scope
>
> Duplicate id:
>
> real_world.cpp:134: error: redefinition of `struct World::addPerson
> (const Person
> &)::rollback_boost_scope_exit_nested_typeofold_id'
> real_world.cpp:121: error: previous definition of `struct
> World::addPerson(const
> Person&)::rollback_boost_scope_exit_nested_typeofold_id'
>
>
> Believe me, I don't like id argument either but I couldn't come up
> with a better solution.

Why not put the code inside the macro?

Example (same as your hello world):
#define MY_BOOST_EXIT( w, x, y ) BOOST_SCOPE_EXIT(w, x) \
                                  y \
                                  BOOST_SCOPE_EXIT_END(w)

int main()
{
     try
     {
         std::string hello("Hello"), world("World");

        MY_BOOST_EXIT( _id, (hello)(world),
        {
                std::clog << world << ", " << hello << "!\n";
        } )

         // other code
     } catch(...) {} /*
     ^ "World, Hello\n" is printed at this point */
}

This way the id is used once. I'm trying to figure out a way to not
use the id at all (when constructing local structs). If I find
something I'll let you know :)

>
>> My solution is CopyConstructable. Many things become interesting
>> when you can copy a chain of commands. It is also bidirectionnal.
>> With a flag at construction, we could invert the order of execution.
>> We could also reorder it in the middle (cannot think of a real use
>> for this, though).
>>
>> BTW, did you check my code? You never told me what you thought of
>> it...
> I looked at it quickly and noticed dynamic allocations.
>
> This code
>> template< class T > void operator()( const T& t ) {
>> vec.push_back( new helper_t<T>(t) );
>> }
> is not exception aware.
>
> You can rewrite it like this:
> std::auto_ptr< helper_t<T> > p(new helper_t<T>(t) );
> vec.push_back( p.get() );
> p.release();

mmmh... I fail to see the difference. There is really two cases
where exceptions may occur:
- operator new( size_t ) throws an exception (Out-Of-Memory). No
memory is allocated.
- push_back reallocs the vector and operator new( size_t ) throws an
exception (Out-Of-Memory). Strong guarantee occurs... (?)

Otherwise, my constructor will not throw an exception (by design).

If I forget something, point it out to me. I really fail to see how
your code is more exception aware than mine, but I'm no exception
expert.

Have a nice day,
Hans

>
> --
> Alexander Nasonov
> http://nasonov.blogspot.com
>
> To be pleased with one`s limits is a wretched state. -- Johann
> Wolfgang von Goethe --
>
> This quote is generated by:
> /usr/pkg/bin/curl -L http://tinyurl.com/veusy \
> | sed -e 's/^document\.write(.//' -e 's/.);$/ --/' \
> -e 's/<[^>]*>//g' -e 's/^More quotes from //' \
> | fmt | tee ~/.signature-quote
> _______________________________________________
> Unsubscribe & other changes: http://lists.boost.org/mailman/
> listinfo.cgi/boost


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk