
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)
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.
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 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.
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 ...
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.
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(); -- 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