裸std::function

对于纯粹的std::function来说,可以通过target方法获取到其函数指针,这样就可以判断两个std::function是否相同。一个简单的例子如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
void func1(int a, int b, void* ptr) {
    printf("func1 %d %d %p\n", a, b, ptr);
}

int main() {

    std::function<void(int, int, void*)> ptr1 = func1;
    std::function<void(int, int, void*)> ptr2 = func1;

    printf("%p %p %d\n",
        *ptr1.target<void(*)(int, int, void*)>(),
        *ptr2.target<void(*)(int, int, void*)>(),
        *ptr1.target<void(*)(int, int, void*)>() == *ptr2.target<void(*)(int, int, void*)>());
}

运行程序后,对应的输出如下:

其中需要注意target方法的用法,其模板参数一定得是函数指针的类型,如果类型不对,那么target将会返回nullptr。

由于target方法使用比较复杂,因此可以对其进行简单的封装,实现如下。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
void func1(int a, int b, void* ptr) {
    printf("func1 %d %d %p\n", a, b, ptr);
}

template<typename T, typename... U>
size_t getAddress(std::function<T(U...)> f) {
    typedef T(fnType)(U...);
    fnType ** fnPointer = f.template target<fnType*>();
    return (size_t)*fnPointer;
}

int main() {
    std::function<void(int, int, void*)> ptr1 = func1;
    std::function<void(int, int, void*)> ptr2 = func1;

    printf("%p %p %d\n",
        getAddress(ptr1),
        getAddress(ptr2),
        getAddress(ptr1) == getAddress(ptr2));
}

std::bind绑定

而对于std::bind绑定得到的函数来说,目前无法获取其函数指针,原因在于std::bind得到的类型太奇葩了。

见下面的代码。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
void func1(int a, int b, void* ptr) {
    printf("func1 %d %d %p\n", a, b, ptr);
}

int main() {
    
    std::function<void(void*)> ptr1 = std::bind(func1, 1, 2, std::placeholders::_1);
    std::function<void(int, int, void*)> ptr2 = std::bind(func1, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);

    printf("%p %p\n",
        ptr1.target<void(*)(void*)>(),
        ptr2.target<void(*)(int, int, void*)>());
}

对应的输出如下。

参考文章

  1. c++11:如何判断std::function对象相同?
  2. C++11如何判断std::bind,std::function对象是否相等
  3. Comparing std::functions for equality?
  4. Compare std::function created with std::bind
  5. C++ trying to get function address from a std::function