将std::function转换为成员函数

35
#include <functional>

struct A
{
    int func(int x, int y)
    {
        return x+y;
    }
};

int main()
{

    typedef std::function<int(int, int) > Funcp;
    A a;
    //Funcp func = std:::bind(&A::func, &a);
    Funcp func = std::bind(&A::func, a, std::placeholders::_1);


    return 0;
}
我在上述两个绑定函数中都遇到了错误:
 error C2825: '_Fty': must be a class or namespace when followed by '::'

语法错误在哪里?我正在使用Visual Studio 2010


1
您需要一个 _2 和 _1 但那似乎不是您遇到的错误。 是否包含了占位符的正确标头? - CashCow
在 _2 变量之后它起作用了。 - hidayat
我希望编译器能够给出正确的错误提示。那是一个明显的错误,但编译器所说的并不明显。 - CashCow
2个回答

38
Funcp func = 
    std::bind(&A::func, &a, std::placeholders::_1, std::placeholders::_2);

2
无论您将a作为对象或指针传递给bind,可能并不重要,因为它允许两者。当然,在指针(指向局部变量)到达被调用的时间时会出现悬挂指针的情况,则这个区别就很重要了。 - CashCow
2
@hidayat 占位符是一个神奇的对象,允许您将参数绑定到它们中。_1 表示第一个参数,_2 表示第二个参数传递给该函数。 - CashCow
好的,这些只有在绑定成员变量时才是必需的吗? - hidayat
4
如果你想要从std::function的调用处“传递”参数,那么这些占位符就是必需的。它们允许你重新排列、复制和省略调用处的参数。在这种情况下,它们是填入分别对应于xy的参数的占位符。 - ltjax

1

我花了一些时间才弄清楚发生了什么。因此,为了让其他人受益,我在这里添加了一些解释。我已经重命名了一些函数和变量,以使它们更加清晰。

#include <functional>

struct A
{
    int MemberFunc(int x, int y) 
    {
        return x+y;
    }
};

int main()
{
    typedef std::function<int(int, int)> OrdinaryFunc;
 
    A a;
    OrdinaryFunc ofunc = std::bind(&A::MemberFunc, a, std::placeholders::_1, std::placeholders::_2);

    int z = ofunc(10, 20); // Invoke like an ordinary function
 
    return 0;
}

类成员函数有一个隐式/隐藏参数,它指向对象(this指针)。这些成员函数只能通过提供对象来调用,这使其与普通函数不同。 std::bind 可以通过传递对象(指针或引用)将成员函数“转换”为普通函数。在成员函数后面的 args 列表中,必须将对象作为第一个参数 (&aa)。在新函数中,对象将被绑定到成员函数的隐式/隐藏参数上,并且在调用时无需传递。未绑定的参数由占位符 _1_2 表示,调用时必须传递。

有没有想法为什么一半的答案在std::bind中使用'&a',而你的使用'a'?我只能让'a'版本起作用。即std::bind(&fn, a, _1,..) - skyfire
对象可以是指针&a或引用a,两者都应该可以工作。检查编译器和版本是否有任何限制。 - ap-osd
1
https://godbolt.org/z/bxqbenjqd - Marek R

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接