vector of queue of unique_ptr

Hi

I understand that if you want a vector of unique_ptr then you need to use vector.push_back( move(myPtr) ) as a unique_ptr is not copyable. However, I'm struggling to create a vector of queues of unique_ptr:

1
2
3
4
5
6
7
        using MsgPtr = std::unique_ptr<int>;
        using MsgQueue = std::queue<MsgPtr>;
        
        std::vector<MsgQueue> mMsgQueues;  

        MsgQueue myQueue;
        mMsgQueues.push_back( std::move(myQueue) );


gives the following error:

1
2
3
/usr/include/c++/7/bits/stl_construct.h:75:7: 
error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&)
[with _Tp = int; _Dp = std::default_delete<int>]’


Thanks
Last edited on
The standard library's container adapters do not play well with move-only types. Further, their move constructors are unconditionally potentially-throwing which is problematic for other reasons.

My solution in practice has been to avoid container adapters entirely. You could rely on a better library implementation.

If this isn't an option, one potential approach is to inherit from std::queue<T> and store the derived class type instead, as follows:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <queue>
#include <vector>
#include <memory>

class queue_unique_ptr_int: public std::queue<std::unique_ptr<int>> 
{
  using base_type = std::queue<std::unique_ptr<int>>;
public:
  using base_type::base_type;
  
  queue_unique_ptr_int(queue_unique_ptr_int const&) = delete;
  queue_unique_ptr_int(queue_unique_ptr_int&&) noexcept = default;
};

int main()
{
  queue_unique_ptr_int q;
  std::vector<queue_unique_ptr_int> v;
  v.push_back(std::move(q));
}


Another approach could involve storing something other than unique_ptr in the queue.
Last edited on
Why use unique_ptr at all? Why not vector<queue<int>> ?
@dyhayden - Because 'int' was just a (bad) example. In reality, 'int' will be a custom type which is dynamically allocated via polymorphism.
I didn't say what the problem is, so I'll do that now.
vector::push_back instantiates the move constructor for its value type if and only if the value type either
a.) provides a non-throwing move constructor; or
b.) does not provide a copy constructor at all.
Otherwise, it instantiates the copy constructor.

queue<unique_ptr>'s move constructor is potentially-throwing, and its copy constructor is present. As such std::vector dutifully follows the rules above and tries to instantiate queue<unique_ptr>'s copy constructor, which results in a hard error.

It may be easier to switch internally to shared_ptr<const T> (which is copyable) at some runtime cost.
Or, you could maybe give the polymorphic object a copyable wrapper.
Last edited on
Topic archived. No new replies allowed.