Is it offensive to implement an idiom of "execution" around objects with an area?

Should cloud objects (with free logic implemented in the constructor and destructor) be used only for resource cleaning (RAII)?

Or can I use it to implement certain aspects of the application logic?

Some time ago I asked about connecting a function in C ++ . It turns out that Bjarne addressed this problem , and the solution he proposes is to create a proxy object that implements operator-> and allocate an object with scope there, "Before" and "after" are implemented in the constructor and destructor of the scope object .

The problem is that destructors should not throw. Therefore, you need to wrap the destructor in a try { /* ... */ } catch(...) { /*empty*/ } block try { /* ... */ } catch(...) { /*empty*/ } . This severely limits the ability to handle errors in the after code.

Should cloud objects only be used to clean resources or can I use it more than? Where do I draw the line?

+4
source share
3 answers

If you meticulously consider a definition in RAII, everything you do using scope rules and calling a destructor that doesn't include freeing resources just isn't RAII.

But who cares? It’s possible that you are really trying to ask

I want X to be executed every time I leave the function Y. Is it insulting to use the same rules and destructor rules that RAII uses in C ++ if X is not a free resource?

I say "No. Scratch it, I say hell. In fact, in terms of code clarity, it would be better to use destructor calls to execute a block of code if you have multiple points of return or possibly exceptions. I would document the fact that your object does something unobvious when destroyed, but it might be a simple comment at the time of instantiation.

Where do you draw the line? I think the KISS principle can help you here. You could probably write your entire program in the body of the destructor, but that would be offensive. In any case, your Spidey Sense will tell you that this is a bad idea. Keep your code as simple as possible, but not simpler. If the most natural way to express a certain functionality is in the body of the destructor, then we express it in the body of the destructor.

+4
source

You need a script where, guaranteedly, the suffix is ​​always executed. It sounds just like RAII working with me. However, I would not actually write like that. I would rather use a chain of member function member methods.

+2
source

I think with C ++ 11, you can safely allow the suffix() call to throw. A strict rule is never "never thrown from the destructor", although this is good advice, instead of the rule :

never throw an exception from the destructor when handling another exception

In the destructor, you can now use std::current_exception , which, I think, checks the "while processing another exception" element of the destructor + exception edit. With this you can do:

 ~Call_proxy() { if (std::current_exception()) { try { suffix(); } catch(...) { // Not good, but not fatal perhaps? // Just don't rethrow and you're ok } } else { suffix(); } } 

I’m not sure that this is actually a good idea in practice, but it’s hard for you to handle if it throws another exception during the throw.

Regarding “this is abuse”, I don’t think that this abuse is more than metaprogramming or writing a?b:c instead of the full-scale if , if that is the right tool for the job! This does not undermine any language rules, simply exploiting them in accordance with the letter of the law. The real problem is the predictability of the behavior of readers unfamiliar with the code, and long-term maintainability, but the problem is for all projects.

+1
source

All Articles