I got the following class:
class Buf {
const uint8_t *data;
size_t size;
public:
Buf() : data(nullptr), size(0) {};
Buf(const uint8_t *data_, size_t size_) : data(data_), size(size_) { };
Buf(Buf&& other) noexcept
: data{std::exchange(other.data, nullptr)}, size{other.size} {};
Buf& operator=(Buf&& other) noexcept {
data = std::exchange(other.data, nullptr);
size = other.size;
return *this;
}
Buf(const Buf& other) = delete;
Buf& operator=(Buf other) = delete;
~Buf()
{
free((void *)data);
}
};
I use this class inside a queue
int main()
{
std::vector<std::queue<Buf>> data;
data.resize(10); // compile error
return 0;
}
I get a long compile error boiling down to:
error: static assertion failed: result type must be constructible from value type of input range
If I in turn use a std::deque instead it seems to compile.
So why does not work with std::queue and how could it be fixed. And why does it seem to work with std::deque
The code: https://godbolt.org/z/Ev86YG1nG
CodePudding user response:
std::queue
is a container adapter; that is, it forwards all of its actual operations to an internal container of a type specified by a template argument. By defualt, this container is std::deque
.
However, std::deque<T>
is not noexcept
moveable. Therefore, when vector<T>
attempts to resize
itself, it cannot use the move operation; it must copy it. And since Buf
is not copyable, neither is std::deque<Buf>
. So vector
tries to copy a non-copyable type; hence the compile error.
There's not really a good solution to this. vector
is not a good type for a queue, since insertion/removal at the front is slow. And deque
is not noexcept
moveable, nor is list
. Maybe if the queues are small, using std::queue<Buf, std::vector<Buf>
might work out performance-wise.
Using std::deque
for the outer container works because many of its operations do not require the type to be moveable or copyable. Insertion/removal from the head/tail don't provoke copying.