在模板中通过成员函数指针调用shared_ptr的成员函数

27

这是一个模板函数,它接受一个指针(或类似于指针的对象)和一个成员函数:

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
相关: https://dev59.com/E1wZ5IYBdhLWcg3wGtDD - Quentin
3个回答

29

std::shared_ptr不支持成员指针访问运算符(即->*.*)。因此,我们不能直接使用->*调用其上的成员函数指针。您可以更改调用语法以使用operator*operator.*,这适用于原始指针和智能指针。

template <typename Ptr, typename MemberFunctor>
int example(Ptr ptr, MemberFunctor func )
{
    return ((*ptr).*func)();
}

LIVE


12

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 的引用,并在其上调用 funcexample 不需要知道指针如何存储,因此不应该需要所有这些额外的重载。

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); 

7

std::shared_ptr没有重载operator ->*。您可以添加一个重载:

template <typename Ptr, typename MemberFunctor>
int example(std::shared_ptr<Ptr> ptr, MemberFunctor func )
{
    return (ptr.get()->*func)();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接