最近我发现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...)();
}
通过这种方式,我的示例也可以无需将operator ->*
添加到shared_ptr
。
问题3:那么,std::bind
现在被视为operator->*
的替代?
答案 0 :(得分:6)
在一个坚果shell中:是std :: bind是成员函数指针的替代。
为什么呢? 因为成员函数指针很糟糕,它们唯一的目的是实现委托,这就是为什么std :: bind和std :: function做
有关如何实现成员函数指针的参考,请参阅我之前的答案here。简单来说,成员函数指针被标准削弱了,因为它们在强制转换后不允许调用;这使得它们对于90%的人想要来自成员函数指针的行为毫无意义:委托。
出于这个原因,std :: function用于表示抽象的“可调用”类型,std :: bind用于将this绑定到成员函数指针。你绝对不应该使用成员函数指针,而是使用std :: bind和std :: function。
答案 1 :(得分:4)
我认为最简单的解决方案是用一对解除引用(->
)和结构引用(*
)运算符替换'structure dereference'(.
)运算符:
template <typename Pointer, typename Function, typename... Args>
auto invoke1(Pointer p, Function f, Args... args) -> decltype(((*p).*f)(args...))
{
return ((*p).*f)(args...);
}
答案 2 :(得分:2)
我相信shared_ptr
没有运算符->*
,因为无法为任意数量的参数实现它(C ++ 11允许为其他用例执行此操作)。此外,您可以轻松地为调用invoke
的智能指针添加get()
函数的重载,因此不希望复杂化接口。