【问题标题】:Passing a function object to std::function将函数对象传递给 std::function
【发布时间】:2017-07-21 15:50:49
【问题描述】:

我在使用函数对象创建 std::function 的实例时遇到了一点麻烦。 (我的环境是使用 Visual Studio 2015 的 C++ 11。)

首先,我有一个在函数对象的参数列表中使用的类。这是说明要点的简化版本。

class X
{
public:
    void zz(int a) const
    {
        std::cout << "X:zz, a = " << a << "." << std::endl;
    }
};

然后这里是函数对象,它在 operator() 方法中使用了 X。

class Y
{
public:
    void operator()(const X& x)
    {
        x.zz(17);
    }
};

现在,我想将 Y 的实例包装在 std::function 中。该函数的类型是 void(const X&),一个将 X 的 const 引用作为参数的 void 函数。方法 Y:operator() 有这个签名。

void test_it
{
    X my_x;

    Y my_y;
    std::function<void(const X&)> f1(my_y);
    f1(my_x); // OK

    std::function<void(const X&)> f2(Y());
    f2(my_x); // cannot convert argument 1 from X to Y

    std::function<void(const X&)> f3(Y);
    f3(my_x); // cannot convert argument 1 from X to Y

    std::function<void(const X&)> f4(Y{});
    f4(my_x); // OK
}

第一个示例 f1 创建 Y 的实例 my_y,并使用此实例创建 f1。这工作正常。 (Y 的内容被移动到 std::function 构造函数中的 std::function 中。)

第二次尝试 f2 在 f2 的构造函数中构造 Y 的实例。当我尝试使用 f2(my_x) 调用它时,编译器会抱怨它无法将参数 1 (my_x) 从 X 转换为 Y。

第三次尝试 f3,我只是在 f3 的 std::function 构造中命名函数对象类,失败的方式与 f2 相同。

最后,f4 起作用了。在这个中,我使用一个空的初始化列表来构造函数对象 Y。

也许有一个简单的解释,但我不明白为什么其中两个用例无法编译。特别是使用 Y() 的 f2 和使用 Y{} 的 f4,与我几乎完全相同。

【问题讨论】:

    标签: c++ function functor


    【解决方案1】:

    对于第二种情况,表达式Y() 试图定义一个返回Y 且不接受任何参数的函数,并将该函数作为参数传递。这被称为most vexing parse

    对于第三种情况,您不能给出类型而不是函数参数。

    Y 的默认构造实例传递给std::function 的正确方法是第4 种情况。

    【讨论】:

    • 感谢您的快速答复。多么恰当的名字,“令人烦恼的解析”。
    • 顺便说一句,我在发布后玩耍时发现,如果我为 Y 类的构造函数提供一个虚拟 int 参数,那么所有 Y 都必须初始化为 Y(0),或 Y{ 0},然后案例 2 使用“f2(Y(0))”以 Y 的实例作为其参数来构造 f2。这也消除了情况的歧义。无论如何,第 4 种情况是最容易使用的。谢谢!!
    • @cha 如果你想使用第二种情况,你可以简单地将表达式包裹在一组括号中。 f2((Y()));
    • 谢谢。第 4 种形式应该同样方便,但很高兴知道这种解决方法。更好的是理解为什么第二个示例的原始代码有歧义,以及为什么额外的括号或初始化大括号消除了歧义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-22
    • 2018-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多