Подтвердить что ты не робот

Может ли queue:: pop вернуть значение сейчас?

Я знаю, что std::queue::pop() возвращает void. По двум причинам:

Fine.

Теперь, если я правильно понимаю новую семантику перемещения С++ 11, вторая больше не является допустимым аргументом.

Итак... единственное, что предотвращает std::queue, чтобы функция pop, возвращающая значение, была в том, что конструктор перемещения бросает?

Мне тяжело думать о ситуациях, когда такой конструктор движений будет бросать. Кто знает пример?

Я думаю, что то же самое можно сказать о std::stack::pop(), std::vector::pop_front(), std::vector::pop_back(), std::deque::pop_front(), std::deque::pop_back(), std::list::pop_front(), std::list::pop_back(), а что нет.

4b9b3361

Ответ 1

Используя умные методы SFINAE, можно было бы получить атомную неметающую pop_and_move() только для типов данных, которые реализуют перемещение без бросания или без металической копии.

Существует даже конструкция noexcept(), чтобы увидеть, может ли что-то метаться.

Одна из новых концепций в С++ 11, в частности, которая расширяет SFINAE, заключается в том, что если тело не компилируется, функция не существует. Таким образом, можно реализовать на основе noexcept().

Я бы сказал, что для обратной совместимости функции потребуется новое имя, что позволяет ей сосуществовать с существующей функциональностью вызова их по отдельности, а не с разбиением контейнеров типов, для которых не существует семантики.

Ответ 2

Существует не так много случаев, когда std::move() может входить в стандартную библиотеку, но есть случаи. Например, если в контейнере используется генератор с установленными состояниями, его дочерние элементы также используют этот распределитель, но он не будет перенесен в результат: это скорее получит построенную по умолчанию версию распределителя (если я правильно удалю). Учитывая, что распределители являются состояниями, это означает, что объект нельзя перемещать, и, таким образом, конструкция перехода сбой исключается. Почему у этого типа есть конструктор перемещения? Ну, потому что он может быть создан с помощью нестационарного распределителя, и в этом случае перемещение не будет выбрасываться. Кроме того, как только мы перейдем к пользовательским классам, мы понятия не имеем, при каких условиях их перемещение может бросить.

Ответ 3

Другая проблема заключается в том, что не каждый класс действительно выигрывает от перемещения, т.е. может иметь только копию ctor.

struct DontLikeMoves{
  // some data, whatever...
  DontLikeMoves(DontLikeMoves const& other){
    // might throw, who knows!
    // and this will even get called for rvalues
  }
};