简体   繁体   English

关于shared_ptr和指向成员运算符` - > *`和`std :: bind`的指针

[英]About shared_ptr and pointer to member operator `->*` and `std::bind`

Recently I discovered that shared_ptr does not have pointer to member operator ->* . 最近我发现shared_ptr没有指向成员运算符的指针->* I created simple example: 我创建了简单的例子:

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: Why is so? Q1:为什么会这样? Why shared_ptr does not have this operator? 为什么shared_ptr没有这个运算符?

I added such operator for shared_ptr and the example started to work: 我为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: Is this right implementation for this operator? Q2:这个运营商是否正确实施? Are there somewhere any "gold" rules how to implement such operator, probably either I reinvented the wheel or go in completely wrong direction, what do you think? 是否有任何“黄金”规则如何实施这样的操作员,可能要么我重新发明轮子或进入完全错误的方向,你怎么看? Is there a way to have a single function implementing this operator instead of as many function as there are placeholders in std... 有没有办法让一个函数实现这个运算符,而不是像std中的占位符一样多的函数...

After that I came to conclusion that std::bind can be used in my invoke method. 之后我得出结论, 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...)();
}

In this way my example also works without need to add operator ->* to shared_ptr . 通过这种方式,我的示例也可以无需向shared_ptr添加operator ->*

Q3: So, is std::bind now considered as a replacement for operator->* ? Q3:那么, std::bind现在被认为是operator->*的替代operator->*

In a nut shell: yes std::bind is a replacement for member function pointers. 在一个坚果shell中: 是的std :: bind是成员函数指针的替代品。

Why? 为什么? because member function pointers are awful, and their only purposes is to implement delegates, which is why std::bind and std::function do 因为成员函数指针很糟糕,它们唯一的目的是实现委托,这就是为什么std :: bind和std :: function做的

For reference on how member function pointers are implemented, see my previous answer here . 有关成员函数指针是如何实现的参考,看看我以前的答案在这里 In simplest terms, member function pointers are crippled by the standard because they do not allow for calls after casts; 简单来说,成员函数指针被标准削弱了,因为它们在强制转换后不允许调用; this makes them quite pointless for the sort of behavior 90% of people want from member function pointers: delegates. 这使得它们对于90%的人想要来自成员函数指针的行为毫无意义:委托。

For this reason, std::function is used to represent an abstract "callable" type, with std::bind being used to bind a this to the member function pointer. 出于这个原因,std :: function用于表示抽象的“可调用”类型,std :: bind用于将this绑定到成员函数指针。 You should absolutely not mess with member function pointers, and instead use std::bind and std::function. 你绝对不应该使用成员函数指针,而是使用std :: bind和std :: function。

I believe the simplest soultion would be to replace 'structure dereference' ( -> ) operator with a pair of derefence( * ) and structure reference( . ) operators: 我相信最简单的灵魂就是用一对derefence( * )和结构引用( . )运算符替换'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...);
}

I believe shared_ptr does not have operator ->* because it's impossible to implement it for arbitrary number of arguments (which C++11 allows to do for other use cases). 我相信shared_ptr没有operator ->*因为不可能为任意数量的参数实现它(C ++ 11允许为其他用例执行)。 Also, you can easily add an overload of invoke function for smart pointers that calls get() , so complicating the interface is not desirable. 此外,您可以轻松地为调用get()智能指针添加invoke函数的重载,因此不希望使接口复杂化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM