Может ли 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()
, а что нет.
Ответы
Ответ 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
}
};