Может ли queue :: pop вернуть значение сейчас? - PullRequest
23 голосов
/ 08 февраля 2012

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

  1. исключительная безопасность: что-то может выдаться после удаления элемента
  2. чтобы иметь возможность вернуть значение по ссылке

Хорошо.

Теперь, если я правильно понимаю новую семантику перемещения C ++ 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() и тому, что нет.

Ответы [ 3 ]

6 голосов
/ 08 февраля 2012

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

5 голосов
/ 08 февраля 2012

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

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

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

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

1 голос
/ 08 февраля 2012

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

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