Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compiler tries to use copy constructor even though I'm moving

Tags:

c++

I'm trying to move things in and out from my thead safe deque:

template <typename T>
class ThreadSafeDeque
{
//..
    T pop_front(void) noexcept
    {
        std::unique_lock<std::mutex> lock{_mutex};

        while (_collection.empty())
        {
            _condNewData.wait(lock);
        }
        auto elem = std::move(_collection.front());
        _collection.pop_front();
        return elem;
    }
private:
    std::deque<T> _collection;            // Concrete, not thread safe, storage.
    //...
}

I created this class to insert into the Deque:

class DecodedFrame
{
public:
    DecodedFrame(){}
    DecodedFrame(const DecodedFrame &decodedFrame) = delete;
    DecodedFrame &operator=(const DecodedFrame &) = delete;
    std::unique_ptr<AVFrame, AVFrameDeleter> avFrame;

Now I'm trying to do

std::shared_ptr<ThreadSafeDeque<DecodedFrame>> decodedFramesFifo;
//add some `DecodedFrame`s to decodedFramesFifo
DecodedFrame decodedFrame = std::move(decodedFramesFifo->pop_front());

But the compiler complains that I deleted the copy assignment constructor, even though I'm trying to use the move assingment constructor. My guess is that it happens because pop_front returns T, not T&. However, returning references makes no sense becaue the object is supposed to leave the deque forever and therefore the reference to it will die.

How can I move things here?

ps: how is it possible for the compiler to copy things when the DecodedFrame holds an unique_ptr? It can't be copied!

like image 936
Guerlando OCs Avatar asked Dec 22 '22 21:12

Guerlando OCs


2 Answers

The problem is you declared your copy c'tor and assignment operator. Doesn't matter that the declaration deletes them, it's still a user supplied declaration. That suppresses the implicit declaration of the move operations. Your options are to

  1. Default the move operations explicitly.
  2. Remove the copy operation declarations, they will still be deleted implicitly on account of the noncopyable member.
like image 106
StoryTeller - Unslander Monica Avatar answered Feb 16 '23 00:02

StoryTeller - Unslander Monica


The copy-ctor/assign operations are deleted (these are also declarations) but that does not implicitly declare/define move-ctor/assign operations.

See p30 of https://fr.slideshare.net/ripplelabs/howard-hinnant-accu2014

You have to declare (default) them.

DecodedFrame(DecodedFrame &&) = default;
DecodedFrame &operator=(DecodedFrame &&) = default;

In order to avoid such frustrating behaviour, you should consider the rule of five.
(https://en.cppreference.com/w/cpp/language/rule_of_three#Rule_of_five)

like image 25
prog-fh Avatar answered Feb 16 '23 01:02

prog-fh