Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a stack have an exception safe method for returning and removing the top element with move semantics?

In an answer to a question about std::stack::pop() I claimed that the reason pop does not return the value is for exception safety reason (what happens if the copy constructor throws).

@Konrad commented that now with move semantics this is no longer relevant. Is this true?

AFAIK, move constructors can throw, but perhaps with noexcept it can still be achieved.

For bonus points what thread safety guarantees can this operation supply?

like image 669
Motti Avatar asked Apr 12 '10 06:04

Motti


People also ask

Can you explain move semantics?

Move semantics allows you to avoid unnecessary copies when working with temporary objects that are about to evaporate, and whose resources can safely be taken from that temporary object and used by another.

Are move semantics important?

A little bit about std::moveMove Semantics is an extremally important concept for one to understand talking about programming in c++. It is a fundamental aspect of the language that may not be that obvious and even more for one coming from another language such as Swift, C#, or Java.

What does the move constructor do?

A move constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying. For more information about move semantics, see Rvalue Reference Declarator: &&. This topic builds upon the following C++ class, MemoryBlock , which manages a memory buffer.


2 Answers

Of course, not every type is move-enabled and C++0x even allows throwing move constructors. As long as constructing the object from an rvalue may throw it cannot be exception-safe. However, move semantics allows you to have many types that are nothrow-constructible given an rvalue source.

Conditional support for this could be done with SFINAE. But even without such a conditional member function nothing stops you from writing:

auto stack = ...;
auto elem = std::move_if_noexcept(stack.back());
stack.pop_back();

which is makes the strong exception guarantee even in case your move constructor doesn't give the strong guarantee.

like image 52
sellibitze Avatar answered Sep 30 '22 13:09

sellibitze


As for the bonus question, that would offer no thread-safety. Consider that, as an example, most implementations of std::vector have three data elements (pointer to beginning of memory, pointer one beyond end of used data, pointer one beyond end of allocated memory). Move semantics allow you to move the contents of the vector without the need to reallocate and copy values, but that has nothing to do with thread safety. You would have to use thread-safe constructs to make the structure thread safe (as moving does not imply by any means atomic)

like image 32
David Rodríguez - dribeas Avatar answered Sep 30 '22 12:09

David Rodríguez - dribeas