3

This post answered my original question: how can I can I template on a member function?

The answer has the code:

struct Foo {
    void Bar() { // do something
    }
};
template <typename TOwner, void(TOwner::*func)()>
void Call(TOwner *p) {
    (p->*func)();
}
int main() {
    Foo a;
    Call<Foo, &Foo::Bar>(&a);
    return 0;
}

I am trying to accomplish the same thing with shared pointers. I found that this does NOT work:

template <typename TOwner, void(TOwner::*func)()>
void Call(std::shared_ptr<TOwner> p) {
    (p->*func)();
}

However, this works

template <typename TOwner, void(TOwner::*func)()>
void Call(std::shared_ptr<TOwner> p) {
    (p.get()->*func)();
}

Is there a better way to accomplish this?

ad_ad
  • 375
  • 3
  • 14

1 Answers1

3

Let me try to address the "Is there a better way to accomplish this?" part of the question: If you can use C++17, there is std::invoke which nicely handles pointer to member functions and smart pointers:

#include <memory>
#include <functional>

auto a = std::make_shared<Foo>();

std::invoke(&Foo::Bar, a); // Ok: pass the shared_ptr itself
std::invoke(&Foo::Bar, *a); // Also ok: pass a reference to the pointee

std::invoke can replace the Call function template in this case, still accepting arbitrary member function pointers.

lubgr
  • 37,368
  • 3
  • 66
  • 117