1
votes

I have a template class for a queue. I also would like be able to store objects contained in a std::unique_ptr.

Normal template specialization is not possible because the std::unique pointer can be instantiated with any type.

Queue code is like this:

bool TQueue<T>::Push(const T& item)
{
  m_Mem[currTail] = item;
}

bool TQueue<T>::Pop( T& item )
{
  item = m_Mem[currHead];
} 

How to make this work for std::unique_ptr types as well, when I need to do m_Mem[curtail] = std::move(item)

1

1 Answers

3
votes

You're approaching the problem from a slightly wrong angle. The move() cannot be inside the Push(), that's too late. It must be outside - you cannot really steal the resources of an arbitrary argument, you must ask the user to actively move the non-copyable resource there. So simply provide an extra overload:

bool TQueue<T>::Push(const T& item)
{
  m_Mem[currTail] = item;
}

bool TQueue<T>::Push(T&& item)
{
  m_Mem[currTail] = std::move(item);
}

That way, your users can actively move their objects into the container when they want (by doing queue.Push(std::move(my_object));.

For Pop(), the situation is even simpler: Pop() removes an element from the queue, so you should always move() it out - you're not retaining any copies:

bool TQueue<T>::Pop( T& item )
{
  item = std::move(m_Mem[currHead]);
}