1

I have read this, this, this and other similar topics. They all show examples of how we can roll back simple changes made to an object in case of an exception to preserve the original state of the object. Yes, if we just push a new element to a vector, it is not hard to pop it back if something goes wrong. But what if we perform more complicated operations on multiple objects than just pushing new elements, and we need to preserve the original state of each object if an exception occures?

// Checkpoint
vec1.erase(
    std::remove_if(vec1.begin(), vec1.end(), [](/*...*/) { /*...*/ }),
    vec1.end());
std::sort(vec2.begin(), vec2.end(), [](/*...*/) { /*...*/ });
std::stable_partition(vec3.begin(), vec3.end(), [](/*...*/) { /*...*/ });

In the above example, if, say, the last stable_partition() function throws std::bad_alloc, this is not so trivial to undo the previous operations made on other containers. We cannot just "unsort" or "unerase" a container as easy as calling pop_back(). How can we gracefully roll back to the checkpoint? Yes, we can make a local copy of each container, perform necessary operations on these copies and then, if everything is ok, we can use noexcept swap. But this approach implies a lot of overhead, especially if the objects are expensive to copy. Can we do something better?

And how about this?

object1.method(); // Changes the internal state of object1
object2.method(); // Changes the internal state of object2
object3.method(); // Throws

If the method of object3 throws, how can we undo the methods of object2 and object1? How do you deal with such cases?

Alexey104
  • 969
  • 1
  • 5
  • 17
  • 1
    If you have an irreversible function then you have to make a copy. No way around that. But you only need one copy at the start, not one per step. If something fails you restore to the initial copy. -- Copies might be expensive. Worse is when they are impossible. -- What you can do is check if all the operations are `noexcept` and only make a copy when not using `if constexpr`. -- Another alternative is to create a vector of indices into the original and then operate on the indices. -- You can merge the copy+erase and only copy those elements you wish to keep, sort and partition them and swap. – Goswin von Brederlow Jul 30 '22 at 14:13

0 Answers0