Может ли в стеке быть безопасный метод исключения и возврата и удаления верхнего элемента с семантикой перемещения?
В ответе на вопрос о std::stack::pop()
Я утверждал, что причина pop
не возвращает значение по соображениям безопасности (что происходит, если конструктор копирования выдает).
Konrad Rudolph отметил, что теперь с семантикой перемещения это уже не актуально. Это правда?
AFAIK, переместить конструкторы могут throw
, но, возможно, с noexcept
это все еще может быть достигнуто.
Для бонусных баллов, какие гарантии безопасности потока может обеспечить эта операция?
2 ответа
Конечно, не каждый тип поддерживает перемещение, а C++0x даже позволяет создавать конструкторы перемещения. До тех пор, пока конструирование объекта из значения r может иметь значение, оно не может быть безопасным для исключения. Тем не менее, семантика перемещения позволяет вам иметь много типов, которые не могут быть построены при наличии источника значения.
Условная поддержка для этого может быть сделана с SFINAE. Но даже без такой условной функции-члена ничто не мешает вам написать:
auto stack = ...;
auto elem = std::move_if_noexcept(stack.back());
stack.pop_back();
что делает гарантию сильного исключения, даже если ваш конструктор ходов не дает строгой гарантии.
Что касается бонусного вопроса, это не обеспечит никакой безопасности потоков. Рассмотрим, что, в качестве примера, большинство реализаций std::vector
иметь три элемента данных (указатель на начало памяти, указатель один за концом используемых данных, указатель один за концом выделенной памяти). Семантика перемещения позволяет перемещать содержимое вектора без необходимости перераспределения и копирования значений, но это не имеет никакого отношения к безопасности потока. Вы должны будете использовать поточно-безопасные конструкции, чтобы сделать структуру потокобезопасной (поскольку перемещение ни в коем случае не подразумевает атомарность)