-1

I am struggling with passing an callable object with overloaded operator bool. It posses also unique_ptr for data so copying was disabled. I am trying to pass such a object to another object whose constructor takes std::function, I believe it is totally legal.

See example:

#include <functional>
#include <memory>
#include <utility>

using namespace std;

class invoker
{
    public:
        invoker(function<bool(void)> fnc_):
            fnc { move(fnc_) }
        {}
        ~invoker() = default;    
    private:
        function<bool(void)> fnc;
};

class action
{
  public:
    action() = default;
    ~action() = default;
    action(const action& rhs) = delete;
    action& operator=(const action& rhs) = delete;

    action(action&& rhs):
        data { move(rhs.data)}
    {
    }
    action& operator=(action&& rhs)
    {
        if (this != &rhs)
        {
            data = std::move(rhs.data);
        }
    }

    bool operator()()
    {
        return true;
    }

  private:    
    unique_ptr<int> data;
};

int main()
{
    auto runner = std::make_unique<invoker>(std::move(action {}));
    //unique_ptr<invoker> runner(new invoker(action() ));

    return 0;
}

Why does compiler complain?

> /usr/include/c++/5/functional:1710:34: error: use of deleted function
> 'action::action(const action&)'
>     __dest._M_access<_Functor*>() =
Lukasz
  • 248
  • 1
  • 7
  • do you see the function signature here `'action::action(const action&)'` ? compiler complains that you have used your copy-constructor of class `action` after you deleted it. – JeJo Aug 06 '18 at 19:38

1 Answers1

2

You pass the std::function by value to the constructor. That means it must be copied. And its contents (like the action object it wraps) can not be copied since you deleted the copy-constructor.

The action object can't be copied anyway since it contain an uncopyable member (the data member variable). You don't need to explicitly delete the copy-constructor, it would have been deleted anyway because of the member.

Your best bet to solve this is to use a lambda as argument instead of creating the (temporary) action object.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • But I am using std::move, doesn't it cast it to r-value and shouldn't then use std::function move constructor? I would also " std::function satisfies the requirements of CopyConstructible and CopyAssignable." isn't it the case ? – Lukasz Aug 06 '18 at 19:51
  • 1
    @Lukasz The problem is that you're not creating a `std::function` directly, instead it has to be created *indirectly* which isn't really possible. You move the `action` object, not the `std::function` object. – Some programmer dude Aug 06 '18 at 19:54
  • I don't think your reason is correct. `std::function foo{action {}};` [also fails to compile](http://coliru.stacked-crooked.com/a/2180d0c04293c098) – NathanOliver Aug 06 '18 at 20:08
  • @Lukasz Indeed my reasoning is partially incorrect (as noted by Nathan). The `std::function` object needs a *copy* of the callable object, which isn't really possible with the `action class. It doens't matter if you move the `action` object or not, the `std::function` object still needs to copy it. And as I noted before, you don't move the `std::function` object, but the `action` object. – Some programmer dude Aug 06 '18 at 20:12