Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
262 views
in Technique[技术] by (71.8m points)

c++ - About shared_ptr and pointer to member operator `->*` and `std::bind`

Recently I discovered that shared_ptr does not have pointer to member operator ->*. 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()
"; } 
};
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? Why shared_ptr does not have this operator?

I added such operator for shared_ptr and the example started to work:

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? 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...

After that I came to conclusion that std::bind can be used in my invoke method.

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.

Q3: So, is std::bind now considered as a replacement for operator->*?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In a nut shell: yes std::bind is a replacement for member function pointers.

Why? because member function pointers are awful, and their only purposes is to implement delegates, which is why std::bind and std::function do

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.

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. You should absolutely not mess with member function pointers, and instead use std::bind and std::function.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...