【问题标题】:Passing callable object to constructor taking std::function [duplicate]将可调用对象传递给采用 std::function 的构造函数 [重复]
【发布时间】:2019-01-13 19:41:51
【问题描述】:

我正在努力传递一个带有重载运算符 bool 的可调用对象。它还拥有用于数据的 unique_ptr,因此禁用了复制。 我正在尝试将这样的对象传递给另一个构造函数采用 std::function 的对象,我相信这是完全合法的。

查看示例:

#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;
}

为什么编译器会抱怨?

> /usr/include/c++/5/functional:1710:34: error: use of deleted function
> 'action::action(const action&)'
>     __dest._M_access<_Functor*>() =

【问题讨论】:

  • 你看到'action::action(const action&amp;)'这里的函数签名了吗?编译器抱怨您在删除后使用了 action 类的复制构造函数。

标签: c++ functional-programming c++14 c++17 move-semantics


【解决方案1】:

您将std::function 按值 传递给构造函数。这意味着它必须被复制。由于您删除了复制构造函数,因此它的内容(如它所包装的 action 对象)不能被复制。

action 对象无论如何都不能被复制,因为它包含一个不可复制的成员(data 成员变量)。您不需要显式删除复制构造函数,无论如何它都会因为成员而被删除。

解决此问题的最佳方法是使用 lambda 作为参数,而不是创建(临时)action 对象。

【讨论】:

  • 但是我正在使用 std::move,它不是将它转换为 r-value 并且不应该使用 std::function 移动构造函数吗?我还会“std::function 满足 CopyConstructible 和 CopyAssignable 的要求。”不是这样吗?
  • @Lukasz 问题是您不是直接创建std::function,而是必须间接创建它,这实际上是不可能的。您移动的是 action 对象,而不是 std::function 对象。
  • 我不认为你的理由是正确的。 std::function foo{action {}};also fails to compile
  • @Lukasz 确实我的推理部分不正确(如 Nathan 所述)。 std::function 对象需要可调用对象的副本,这对于action class. It doens't matter if you move the action` 对象来说实际上是不可能的,std::function 对象仍然需要复制它。正如我之前提到的,您不会移动std::function 对象,而是移动action 对象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-27
  • 1970-01-01
  • 1970-01-01
  • 2018-07-01
  • 1970-01-01
相关资源
最近更新 更多