RAII object to restore previous value

Perhaps I thought about this, but consider the following example:

bool some_state = false; // ... later ... some_state = true; do_something(); some_state = false; 

Now imagine what do_something() can throw. We will not set some_state back to false . It would be nice to have some kind of automatic stack that pushes / pops up based on the memory area to remember previous values:

 { scoped_restore res( some_state, true ); // This sets some_state to true and remembers previous value (false) do_something(); } // At this point, res is destroyed and sets some_state back to false (previous value) 

Does boost have something like this? Of course, I can write my own object, but I want to make sure that I do not invent the wheel first. I am using C ++ 03 on MSVC, so I cannot use any new C ++ 11, unfortunately :(

+6
source share
2 answers

Boost has something like this. It is called state_saver. He is buried in the serialization library, but it is documented and apparently officially (i.e. Not in any particular namespace).

http://www.boost.org/doc/libs/1_56_0/libs/serialization/doc/state_saver.html

Demo: http://rextester.com/NVXUG70771

+1
source

You bark the right tree. Bjarne Stroustrup highly recommends RAII for exception handling, not try / catch / finally. In the latest issue of the C ++ Programming Language (4th edition), he fully expounds his recommended method in Chapter 13, Exception Handling.

It is very difficult to replace an entire chapter, so at first I would recommend just reading the chapter. However, the basic idea is to use composition and allow the designer to protect the resource.

So, if you have a class A that protects 3 resources that everyone can throw up (maybe some memory), you instead let the subobject protect each of its constructor (not constructor A). The key point is that if the constructor is allowed to complete the job, it is guaranteed (by language) that the destructor will be called. So, in the top-level constructor, initialize the subobjects as follows:

 class B{ public: B( int n ) { //allocate memory (may throw) } void *secured_memory; ~B(){ //release memory } } class A{ public: A( int n ) :b{n}, c{n}, d{n} { //will not complete if B, C or D throws //but because the constructors of B and C completed //their destructors will be invoked if D throws } B b; C c; D d; } 

Imagine that there is a class C and a class D, and they are structured as B. Thus, in your example above, some_state will be protected through a class such as B, C or D.

Another key point. You must protect only one resource in each class of subobjects. Thus, the resource is acquired, and the designer is allowed to exit (in this way, a call is made to the destructor, which will safely release the resource) or he throws (therefore, does not acquire the resource).

0
source

Source: https://habr.com/ru/post/950134/


All Articles