I have a class NoCopy that is movable, but not copiable.
I need to make a vector of 3 queues of NoCopy. I can create an empty one, but there is no way to add any element.
I can make a std::vector<NoCopy> or std::queue<NoCopy> and populate them. But not for std::vector<std::queue<NoCopy>>.
MWE:
#include <iostream>
#include <vector>
#include <queue>
class NoCopy{
public:
NoCopy() = default;
NoCopy& operator = (const NoCopy&) = delete;
NoCopy(const NoCopy&) = delete;
NoCopy(NoCopy&&) = default;
NoCopy& operator = (NoCopy&&) = default;
};
using QNC = std::queue<NoCopy>;
int main(void) {
QNC q;
q.push(std::move(NoCopy()));
std::vector<NoCopy> ncvec;
ncvec.emplace_back();
std::cout << "Queue size " << q.size() << ", vector size: " << ncvec.size() << std::endl;
std::vector<QNC> qvec;
//????
return 0;
}
Any ideas?
By default,
std::queueis based onstd::deque, which is not guaranteed to be nothrow-movable. Neither is the other suitable standard container,std::list; these rules allow implementations that always allocate at least one node/block.std::vectoruses copies to reallocate when moving might throw (so as to guarantee exception safety) unless the type is not copyable at all, and those two containers also do not propagate non-copyability from their element type but just fail if you try. The last could be said to be a defect in the standard, since expectations for such propagation keep going up, but fixing it is incompatible with support for incomplete types:Note that both libstdc++ and libc++ do make those two containers nothrow-movable (as of version 9 in each case), which is a permitted extension, but MSVC’s STL does not.
You can still use
std::vector<QNC> v(3);; the constructor “knows” that reallocation is never necessary. Or you can provide a wrapper (e.g., a class derived fromstd::queue) that is non-copyable or is nothrow-movable; the former will waive the exception safety ofstd::vector, while the latter will callstd::terminateif moving the underlying container does throw.