【问题标题】:Why am I getting "error: no match for ‘operator->*’" when the parameters on both sides look correct?当两边的参数看起来正确时,为什么我得到“错误:不匹配'operator-> *'”?
【发布时间】:2021-11-18 16:41:36
【问题描述】:

我正在尝试从模板内的模板函数中调用函数。

但是,调用本身无法编译,而是出现以下错误:

/home/alexis/tmp/b.cpp: In instantiation of ‘bool callback_manager<C>::call_member(F, ARGS ...) [with F = bool (main()::foo::*)(int, int, int); ARGS = {int, int, int}; C = std::vector<std::shared_ptr<main()::foo> >]’:
/home/alexis/tmp/b.cpp:43:47:   required from here  
/home/alexis/tmp/b.cpp:15:19: error: no match for ‘operator->*’ (operand types are ‘std::shared_ptr<main()::foo>’ and ‘bool (main()::foo::*)(int, int, int)’)  
        if(!(c->*func)(&args...))  
            ~~^~~~~~~~

这是我正在尝试编译的代码的简化版本:

#include    <memory>
#include    <vector>

template<typename C>
class callback_manager
{
public:
    template<typename F, typename ... ARGS>
    bool call_member(F func, ARGS ... args)
    {
        C callbacks(f_callbacks);
        for(auto c : callbacks)
        {
            if(!(c->*func)(args...))
            {
                return false;
            }
        }
        return true;
    }

private:
    C f_callbacks;
};

int main()
{
    class foo
    {
    public:
        typedef std::shared_ptr<foo>    pointer_t;
        typedef std::vector<pointer_t>  vector_t;

        bool the_callback(int, int, int)
        {
            return true;
        }
    };

    callback_manager<foo::vector_t> m;

    m.call_member(&foo::the_callback, 5, 13, 7);

    return 1;
}

看参数,好像都是正确的:

std::shared_ptr<main()::foo>

bool (main()::foo::*)(int, int, int)

【问题讨论】:

    标签: c++ templates indirection


    【解决方案1】:

    事实是-&gt;* 运算符不适用于std::shared_ptr&lt;&gt;

    解决方案是像这样检索裸指针:

    if(!(c.get()->*func)(args...)) ...
    

    然后按预期编译。

    你也可以改写如下,我觉得比较隐晦:

    if(!(*c).*func)(args...)) ...
    

    (即shared_ptr::operator * ()函数返回共享指针持有的指向对象,因此在这种情况下使用.*运算符。)

    【讨论】:

    • @JaMiT 实际上,我进行了编辑以修复该句子。感谢您指出这一点。
    【解决方案2】:

    替换

    if(!(c->*func)(args...))
    

    if(!(std::cref(func)(c, args...)))
    

    使用 C++ 的 INVOKE 机制。或者直接使用std::invoke

    标准中的 INVOKE 概念和 std::invoke,旨在与 pmfs 和智能指针一起使用。

    同时,-&gt;* 不会被智能指针重载。所以这样直接使用是行不通的。

    作为附带的好处,现在可以将非成员函数作为 func 传入。

    【讨论】:

    • 在我的完整实现中,c 可以是直接函数(可以是std::bind())或对象。现在我想知道这是否可以在我不必创建专业化的情况下与这两者一起使用。
    • @alexis 如果 c 是一个函数,那么 func 是什么?或者是不是call_member之外的另一种方法?当然,call(args...) 可以只是std::invoke(c,args...); call on 或 call 成员移动 c 之前的参数之一。
    猜你喜欢
    • 1970-01-01
    • 2019-03-18
    • 1970-01-01
    • 2016-07-30
    • 1970-01-01
    • 2021-06-25
    • 2013-01-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多