最近我发现shared_ptr
没有指向成员的运算符->*
。我创建了一个简单的示例:
template <typename Pointer, typename Function, typename... Args>
auto invoke1(Pointer p, Function f, Args... args) -> decltype((p->*f)(args...))
{
return (p->*f)(args...);
}
struct A {
void g() { std::cout << "A::g()\n"; }
};
int main() {
A a;
invoke1(&a, &A::g); // works!!
std::shared_ptr<A> sa = std::make_shared<A>();
invoke1(sa, &A::g); // compile error!!
}
Q1:为什么这样呢?为什么shared_ptr没有这个运算符?
我为shared_ptr
添加了这样的运算符,示例开始工作:
template <typename T, typename Result>
auto operator ->* (std::shared_ptr<T> pointer, Result (T::*function)()) ->decltype(std::bind(function, pointer))
{
return std::bind(function, pointer);
}
template <typename T, typename Result, typename Arg1>
auto operator ->* (std::shared_ptr<T> pointer, Result (T::*function)(Arg1 arg1)) ->decltype(std::bind(function, pointer, std::placeholders::_1))
{
return std::bind(function, pointer, std::placeholders::_1);
}
Q2:这个运算符的实现是否正确?是否有任何“黄金”规则来实现这样的运算符,可能我重新发明了轮子或者走了完全错误的方向,你认为呢?有没有一种方法可以使用单个函数来实现此运算符,而不是像 std 中占位符数量那么多的函数...
之后,我得出结论,std::bind
可以在我的 invoke
方法中使用。
template <typename Pointer, typename Function, typename... Args>
auto invoke2(Pointer p, Function f, Args... args)
-> decltype(std::bind(f, p, args...)())
{
return std::bind(f, p, args...)();
}
通过这种方式,我的示例也可以正常工作,无需向 shared_ptr
添加 operator ->*
。
Q3: 那么,现在是否认为 std::bind
是 operator->*
的替代品?