Вызов функции-члена в shared_ptr через указатель функции-члена в шаблоне
Это функция шаблона, которая принимает указатель (или объект-указатель) и функцию-член:
template <typename Ptr, typename MemberFunctor>
int example(Ptr ptr, MemberFunctor func )
{
return (ptr->*func)();
}
Если работает с обычным указателем:
struct C
{
int getId() const { return 1; }
};
C* c = new C;
example(c, &C::getId); // Works fine
Но это не работает с интеллектуальными указателями:
std::shared_ptr<C> c2(new C);
example(c2, &C::getId);
Сообщение об ошибке:
error: C2296: '->*' : illegal, left operand has type 'std::shared_ptr<C>'
Почему? и как сделать что-то, что работает с обоими?
Ответы
Ответ 1
std::shared_ptr
не поддерживает доступ к указателю на элемент оператора (т.е. ->*
и .*
). Таким образом, мы не можем ссылаться на указатели функций-членов с помощью ->*
на нем напрямую. Вы можете изменить вызывающий синтаксис для использования operator*
и operator.*
, который работает как для сырых указателей, так и для интеллектуальных указателей.
template <typename Ptr, typename MemberFunctor>
int example(Ptr ptr, MemberFunctor func )
{
return ((*ptr).*func)();
}
LIVE
Ответ 2
std::shared_ptr
не имеет operator->*
. У вас есть два основных варианта:
Вы можете написать перегрузку, которая принимает std::shared_ptr
(возможно, одну для std::unique_ptr
):
template <typename T, typename MemberFunctor>
int example(std::shared_ptr<T> ptr, MemberFunctor func )
{
return ((ptr.get())->*func)();
}
Однако я бы предложил просто сделать example
ссылкой на T
и называть func
на нем. example
не нужно ничего знать о том, как хранится указатель, поэтому он не должен требовать всех этих дополнительных перегрузок.
template <typename T, typename MemberFunctor>
int example(T&& t, MemberFunctor func )
{
return (std::forward<T>(t).*func)();
}
Теперь, если у вас есть std::shared_ptr<T>
, вы вызываете example
как:
example(*my_shared_ptr, my_func);
Ответ 3
std::shared_ptr
не перегружает operator ->*
. Вы можете добавить перегрузку:
template <typename Ptr, typename MemberFunctor>
int example(std::shared_ptr<Ptr> ptr, MemberFunctor func )
{
return (ptr.get()->*func)();
}