最近我发现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->*
的替代品?
最佳答案
简而言之:是的,std::bind 是成员函数指针的替代品。
为什么? 因为成员函数指针很糟糕,它们的唯一目的是实现委托(delegate),这就是为什么 std::bind 和 std::function 做
关于如何实现成员函数指针的引用,请参阅我之前的回答 here .用最简单的话来说,成员函数指针被标准削弱了,因为它们不允许在转换后调用;这使得它们对于 90% 的人希望从成员函数指针获得的那种行为毫无意义:委托(delegate)。
因此,std::function 用于表示抽象的“可调用”类型,std::bind 用于将 this 绑定(bind)到成员函数指针。你绝对不应该乱用成员函数指针,而是使用 std::bind 和 std::function。
关于c++ - 关于 shared_ptr 和指向成员运算符 `->*` 和 `std::bind` 的指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17696664/