This is a bit tricky. All std::vector<T> functions that can increase the size of the vector have to do it in an exception-safe way if either of these two things are true:
T has a move constructor that guarantees it will never throw any exceptions; or,
T has a copy constructor.
So in most implementations, if T has a move constructor declared nothrow or equivalent, vector will use the move constructor of T for those operations. If not, and T has a copy constructor, vector will use the copy constructor, even if T has a move constructor.
And the problem here is that std::queue always declares it has a copy constructor, even if that copy constructor can't actually be instantiated, and always declares it has a move constructor that might throw, even if the container member's move constructor guarantees it won't throw.
The Standard specifies these in [queue.defn] as:
namespace std { template<class T, class Container = deque<T>> class queue { // ... public: explicit queue(const Container&); explicit queue(Container&& = Container()); // ... }; }
This class template definition could be improved in a couple of ways to be more "SFINAE-friendly" and avoid issues like the one you ran into. (Maybe somebody could check for other classes with similar issues and submit a proposal to the Library Working Group.)
Change the move constructor to promise not to throw if the Container type makes the same promise, typically done with language like:
explicit queue(Container&& rhs = Container()) nothrow(see below);
Remarks: The expression inside noexcept is equivalent to is_nothrow_move_constructible_v<Container>.
Change the copy constructor to be deleted if the Container type is not copyable, typically done with language like:
explicit queue(const Container&);
Remarks: This constructor shall be defined as deleted unless is_copy_constructible_v<Container> is true.
push_backmakes a copy. To create an object in place, useemplace_back.std::queueis replaced bystd::vector; doesn't work with the default queue underlier ofstd::deque. But it does work fine tomoveadequethat isn't in a vector. Weirddequethat isn't in avector. The operation will not benoexcepthowever.vectorjust doesn't like potentially throwing moves (see aschepler's answer for details).