Binding to Privately Inherited Member Functions
考虑代码
#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