考虑代码

#include <functional>

class Base {
public:
    void Foo(int n)
    {
        printf("the value is %d", n);
    }
};

class Derived : Base {
public:
    using Base::Foo;
};

int main()
{
    auto f = std::bind(&Derived::Foo, std::placeholders::_1, 10);
    Derived o;
    f(&o);
    return 0;
}

编译会提示出错,错误信息类似:_Failed to specialize function template ‘unknown-type std::_Binder<std::_Unforced,void (__cdecl Base::* )(int),const std::_Ph<1> &,int>::operator ()(Unbound &&…) const’

根本原因是,即使前面使用了 using Base::Foo;, 也只是改变了这个函数在子类中的可见性,影响名字查找;并没有真的在子类中添加了这个函数,因此 &Derived::Foo 实际上获取的类型是 void (Base::*)(int),而正是这个类型影响了 std::bind() 的实例化。

因此当后面用 Derived 的实例去调用 function object 时会失败。

Stackoverflow 上有一个类似的问题,可以参考。

Workaround

(1) 子类增加一个 call-wrapper

然而大多数采用 private-inheritance 而不是 composition 的情况下,都是避免添加各种 call-wrapper

(2) 绑定 lambda 而不是函数指针

这是一个推荐的做法

(3) 强行用 reinterpret_cast<>

呃… let’s don’t be evil