4 ms·
You are probably referring to the defer() macro, which is well suited for some cases and not too unergonomic to use. I've used this for multiple years, and I st
by jstimpfle 5y ago
You are probably referring to the defer() macro, which is well suited for some cases and not too unergonomic to use. I've used this for multiple years, and I still love it, together with X-macros they are some of the most important tricks I would advice any C programmer to try out.
Sometimes with defer() you might get a difficult to read error message when you're doing something wrong, but it's galactically easier to deal with than the standard STL error spew that so many C++ programmers have just come to accept, and it's hard to do something wrong in the first place (just put simple expressions as arguments).
A comparison of defer() with RAII is not that meaningful, as they are totally different things. RAII is this complicated system that leads to (requires) other more complicated stuff like {default,copy,move,assignment...}{constructor/destructors} as well as exceptions, with all sort of terrible interactions and implicit behaviour, that can easily get out of hand and make your code an unreadable mess and/or produce terribly inefficient (piece-meal allocations/function calls) and slow-compiling code (huge header includes).
In the simple situations where defer() is a win, if you use (just) RAII instead, you always have to declare a class out-of-line first (using weird braces and all) to get ad-hoc behaviour, while with defer() macro you can just make something up on the spot, which is often a better way.
I'm not saying there can't be experienced coders who use RAII well in some situations, but personally I opt to just not use it, since the price seems far to high for the benefits, outside of say primitive use in leetcode assignments.
- ogoffart 5y agoThe problem with defer is that it is a macro with all its problem. Imagine such code for (int i = 0; i < files_count; ++i) { file_handle_t handle = open_file(files[i]); defer(close_file(handle)) { // ... if (some_condition) { close_file(handle); break; } // ... } } But this doesn't work because you did not know or you forgot that `defer` was implemented with a `for` inside and so the `break` or `continue` goes out of the wrong loop. and that's just one example of the many thing that can go wrong because it is a macro. On the other hand, with RIAA, you just have your file_handle that automatically close so you can't forgot to close it, and the rules are well known and not that difficult to understand.
- jstimpfle 5y agoIt's indeed a problem that has happened to me, which is why I like to make the macro like for DEFER(init, exit) { } or at least give it a name that indicates clearly that this is syntactically a loop. That's like with some iteration macros that I like to use as well from time to time. The basic idea is to never try to hide what you're doing, since that will backfire. You can still take a balanced approach with DRY and separation of concerns principles, which can lead to reasonable macros. > and that's just one example of the many thing that can go wrong because it is a macro. I'm inclined to say that nothing can go wrong in above usage, or at the very least it would take criminal energy to break it (I really can't come up with a case right now). It's perfectly doable to write safe macros with only a little experience. Follow these simple rules when defining macros: 1) parenthesize usages of macro params, and parenthesize the whole macro body if it is a complete expression. 2) Use parameters that take syntactical expressions only once, to prevent evaluating side-effects (like x++) multiple times. Linux kernel even allows for declaration of local variables in macros by using expression statement blocks (GCC extension). Although I've never had a need for them, I believe that with this approach you can fulfill rule 2) in all possible situations. You can improve macro safety in cases where you need to define a macro that is a little dangerous by just capitalizing the macro's name to make clear at the call site to be a little bit careful here. The thing is, there is no need to be 100% safe. It's very good to be 99% safe and have a simple to use mechanism. Because there are always so many other ways to break your programming, and if you're trying to be 100% safe at the cost of being twice as hard to use, that's effectively a net loss because you're provoking problems in other ways. > On the other hand, with RIAA, you just have your file_handle that automatically close so you can't forgot to close it, and the rules are well known and not that difficult to understand. Could agree if it's a file handle or something other off-the-shelf thing where you don't have to make the class yourself, and everybody instinctively is aware of the implicit behaviour. Otherwise, I very much like the more explicit behaviour and ad-hoc convenience that a defer() macro gives me.