C++11 如何检查std::函数是否绑定到特定对象';成员函数?

C++11 如何检查std::函数是否绑定到特定对象';成员函数?,c++11,callback,function-pointers,C++11,Callback,Function Pointers,我正在寻找一种检查std::function指针是否绑定到特定对象的成员函数的方法。我知道std::函数本身没有“==”运算符。然而,我遇到了std::function::target方法,原则上它应该能够给我指针指向的函数的地址。因此,我的出发点是: bool MyClass::isThePointerSetToMyMethod(std::function<void (const char*, string)> const& candidate) { // Crea

我正在寻找一种检查std::function指针是否绑定到特定对象的成员函数的方法。我知道std::函数本身没有“==”运算符。然而,我遇到了std::function::target方法,原则上它应该能够给我指针指向的函数的地址。因此,我的出发点是:

bool MyClass::isThePointerSetToMyMethod(std::function<void (const char*, string)> const& candidate)
{
    // Create a pointer to the local reportFileError function using the same syntax that we did in the constructor:
    std::function<void (const char *, string)> localFn = std::bind(&MyClass::theLocalMember, this, 
                                                                   std::placeholders::_1, std::placeholders::_2);

    // Find the target
    auto ptr1 = localFn.target< std::function<void (const char *, string)> >();

    // Find the target of the candidate 
    auto ptr2 = candidate.target< std::function<void (const char *, string)> >();

    // Compare the two pointers to see whether they actually point to the same function:
    if (!ptr1 || !ptr2) return false;
    if (*ptr1 == *ptr2)
        return true;
    else
        return false;
}
bool MyClass::isThePointerSetToMyMethod(std::function const&candidate)
{
//使用与构造函数中相同的语法创建指向本地reportFileError函数的指针:
std::function localFn=std::bind(&MyClass::theLocalMember,this,
std::占位符::_1,std::占位符::_2);
//找到目标
auto ptr1=localFn.target();
//找到候选人的目标
auto ptr2=candidate.target();
//比较这两个指针,看看它们是否实际指向同一个函数:
如果(!ptr1 | |!ptr2)返回false;
如果(*ptr1==*ptr2)
返回true;
其他的
返回false;
}
这不起作用,原因是“ptr1”和“ptr2”的值总是返回为null。根据,这一定是因为我为目标指定的类型不正确

<如果我查看目标Type类型(LoalFn)实际上是什么(使用Visual C++ 2013),那有点吓人:

class std::_Bind<1,void,struct std::_Pmf_wrap<void (__thiscall MyClass::*)(char const *, string),void,class MyClass,char const *,string>,class MyClass * const,class std::_Ph<1> &,class std::_Ph<2> &>
class std::\u Bind
尽管如此,target_type(candidate)给出了相同的结果,所以我想我应该试试typedef:

bool MyClass::isThePointerSetToMyMethod(std::function<void (const char*, string)> const& candidate)
{
    typedef class std::_Bind<1,void,struct std::_Pmf_wrap<void (__thiscall MyClass::*)(char const *, string),void,class MyClass,char const *,string>,class MyClass * const,class std::_Ph<1> &,class std::_Ph<2> &> wally;

    // Create a pointer to the local reportFileError function using the same syntax that we did in the constructor:
    std::function<void (const char *, string)> localFn = std::bind(&MyClass::theLocalMember, this, 
                                                                   std::placeholders::_1, std::placeholders::_2);

    // Find the target
    auto ptr1 = localFn.target< wally >();

    // Find the target of the candidate 
    auto ptr2 = candidate.target< wally >();

    // Compare the two pointers to see whether they actually point to the same function:
    if (!ptr1 || !ptr2) return false;
    if (*ptr1 == *ptr2)
        return true;
    else
        return false;
}
bool MyClass::isThePointerSetToMyMethod(std::function const&candidate)
{
typedef类别标准:u Bind wally;
//使用与构造函数中相同的语法创建指向本地reportFileError函数的指针:
std::function localFn=std::bind(&MyClass::theLocalMember,this,
std::占位符::_1,std::占位符::_2);
//找到目标
auto ptr1=localFn.target();
//找到候选人的目标
自动ptr2=候选。目标();
//比较这两个指针,看看它们是否实际指向同一个函数:
如果(!ptr1 | |!ptr2)返回false;
如果(*ptr1==*ptr2)
返回true;
其他的
返回false;
}
唉,这不能让我更进一步;ptr1和ptr2的值仍然为空

所以现在我已经没有主意了。有没有人读过这篇文章,他知道:

(1) 指向类的成员函数的std::函数指针的typedef的适当形式,或

(2) 实现我的最终目标的更好方法是,判断std::function指针是否指向特定对象的成员函数

[背景,以防有人感兴趣:我这样做的原因是我有一个回调表,根据系统所处的状态,不同的回调被设置为不同的函数;这使得状态控制非常简单,因为这意味着在给定的上下文中,我可以调用给定的回调,并且知道func所采取的操作我调用的操作将适用于当前状态,而不必知道该状态实际上是什么。通常,当实例化一个将更改系统状态的对象时,它将控制相关回调并将它们绑定到适合其所处状态的任何本地成员函数。然而,在这种情况下,对象的析构函数应该将回调返回到其原来的状态,以便它们不会指向任何内容


很少情况下,一个对象可以将回调绑定到其构造函数中的成员函数,但在调用其析构函数之前,另一个对象可以控制相同的回调本身,并将它们重新绑定到自己的成员函数。如果发生这种情况,则第一个对象的析构函数需要能够识别这种情况,并且退出时不影响回调对第二个对象方法的分配。执行此操作的明显方式是,析构函数能够检查回调是否仍分配给其自己的方法,如果没有分配,则不必理会。]

将回调表充实到一个管理该表的类中。对该表的所有修改都应通过该类的接口完成。在内部,您将维护一个堆栈式结构,允许您撤消对回调表所做的更改。Barebones接口类似于:

class CallbackTable
{
public:
bool ApplyChanges(...)
{
//Push the old values of the entries that would be changed here into your change-tracker stack and modify the table
}

bool UnApplyChanges(...)
{
//Pop the change-tracker stack and restore the table to the state it was in before the most recent change was applied.
}
};

您实际上不打算使用返回类型
std::bind
。这听起来确实像是XY问题。稍微重新构造回调表以存储指向对象的指针如何?为什么不让回调表更智能,允许它应用并取消应用对其存储的回调的更改?@T.C.,是的,甚至是我认为这听起来像XY问题,这就是为什么我在一个典型的堆栈溢出问题上说了一些关于X的问题。@普拉罕,这实际上是一个相当好的主意;目前我的回调表是一组STD::函数在C样式结构中保存,但是它用它自己的BooKePi所需的方法使它成为C++类。ng可能是一个很好的解决方法。您是否愿意将其作为一个答案发布,这样我就可以选择接受它了?我一直在考虑的另一个解决方法是为每个函数提供一个可选的第三个参数,该参数如果存在,将返回一个UUID来明确标识它。不过,我认为您的参数听起来更简洁。