Это немного сложно.Все std::vector<T>
функции, которые могут увеличить размер вектора, должны делать это безопасным для исключений способом, если любая из этих двух вещей верна:
T
имеет ходконструктор, который гарантирует, что он никогда не вызовет никаких исключений;или
T
имеет конструктор копирования.
Так что в большинстве реализаций, если T
имеет конструктор перемещения, объявленный nothrow
или эквивалентный vector
будет использовать для этих операций конструктор перемещения T
.Если нет, и T
имеет конструктор копирования, vector
будет использовать конструктор копирования, даже если T
имеет конструктор перемещения.
И проблема здесь в том, что std::queue
всегда объявляет, что имеетконструктор копирования, даже если этот конструктор копирования на самом деле не может быть создан, и всегда объявляет, что у него есть конструктор перемещения, который может генерировать, даже если конструктор перемещения члена контейнера гарантирует, что он не выбросит.
Стандартопределяет их в [queue.defn] как:
namespace std {
template<class T, class Container = deque<T>>
class queue {
// ...
public:
explicit queue(const Container&);
explicit queue(Container&& = Container());
// ...
};
}
Это определение шаблона класса может быть улучшено несколькими способами, чтобы быть более «дружественным к SFINAE» и избегать проблем, подобных той, с которой вы столкнулись.(Может быть, кто-нибудь может проверить другие классы с похожими проблемами и отправить предложение в рабочую группу библиотеки.)
Измените конструктор перемещения, чтобы он обещал не бросать, если тип Container
делаетто же самое обещание, обычно выполняемое на языке, таком как:
explicit queue(Container&& rhs = Container()) nothrow(see below);
Примечания: Выражение внутри noexcept
эквивалентно is_nothrow_move_constructible_v<Container>
.
Измените конструктор копирования, который будет удален, если тип Container
не копируется, как правило, выполняется с помощью такого языка, как:
explicit queue(const Container&);
Примечания: Этот конструктор должен быть определен как удаленный, если толькоis_copy_constructible_v<Container>
is true
.