不能存储会员功能"在模板中

时间:2018-03-13 15:21:06

标签: c++ templates

我想"在我班级中存储会员功能"以后在某些情况下调用它。但我无法修复我的代码来存储带参数的成员函数。 Heres是我的代码:

class IMemFn
{
public:
    IMemFn() {}
    IMemFn(const IMemFn& other) = delete;
    IMemFn& operator=(const IMemFn& other) = delete;
    IMemFn(IMemFn&& other) = delete;
    IMemFn& operator=(IMemFn&& other) = delete;
    virtual ~IMemFn() {}

    virtual void func(const std::string& name, const std::string& value) = 0;
};

template<typename ReturnType, class Class>
class MemFn final : public IMemFn
{
public:
    typedef ReturnType(Class::*Method)();

    MemFn(Class* object, Method method) : IMemFn(), m_object(object), m_method(method) {};

    virtual void func(const std::string& name, const std::string& value) override final
    {
        (m_object->*m_method)(name, value);
    };

private:
    Class* m_object;
    Method m_method;
};



class Test
{
public:
    template <class Class, typename Method>
    void addMemFn(Class* obj, Method method) {
        auto memFn = new MemFn<typename std::result_of<decltype(method)(Class)>::type, Class>(std::forward<Class*>(obj), std::forward<Method>(method));
        m_memFns.push_back(memFn);
    }

private:
    std::list<IMemFn*> m_memFns;
};


class SomeClass
{
public:
    void funcAll(const std::string& name, const std::string& value) { std::cout << "SomeClass func"; }
};

class SomeClass2
{
 public:
     void func2(const std::string& name, const std::string& value) { std::cout << "SomeClass2 func"; }
};


int main()
{
    Test test;
    SomeClass someClass;
    SomeClass2 someClass2;

    test.addMemFn(&someClass, &SomeClass ::funcAll);
    test.addMemFn(&someClass2, &SomeClass2::func2);

    return 0;
}

但编译失败并显示以下消息:'type': is not a member of 'std::result_of<Method (Class)>

并在此行中:(m_object->*m_method)(name, value);

但是如果我尝试保存没有参数的成员函数,那么这个错误就不会出现。

感谢您的帮助!

2 个答案:

答案 0 :(得分:1)

这里需要进行一些更改才能进行编译:

  • 首先std::result_of<decltype(method)(Class)需要std::result_of<Method(Class*,std::string,std::string) 因为它是一个成员函数,它指向this加上两个参数。

  • 看起来MemFn中的函数inform应该重命名为func

  • Method需要添加为MemFn的模板参数。

然后,您可以通过test对象调用成员函数,例如:

(*test.m_memFns.begin())->func("a", "b");

但是,在满足界面void IMemFn::func(...)的同时,您将无法从这些成员函数返回不同类型。

答案 1 :(得分:0)

感谢大家的回答!看起来我很累,因为这些该死的模板。我使用std :: functions和std :: bind,现在一切都很简单轻松。所以,我的最终代码是:

class Test
{
public:
    template <class Class, typename Method>
    void addMemFn(Class* obj, Method method) {
        auto func = std::bind(method, obj, std::placeholders::_1, std::placeholders::_2);
        m_funcs.push_back(func);
    }

private:
    std::list<std::function<void(const std::string&, const std::string&)>> m_funcs;
};


class SomeClass
{
public:
    void funcAll(const std::string& name, const std::string& value) { std::cout << "SomeClass func"; }
};

class SomeClass2
{
public:
    void func2(const std::string& name, const std::string& value) { std::cout << "SomeClass2 func"; }
};


int main()
{
    Test test;
    SomeClass someClass;
    SomeClass2 someClass2;

    test.addMemFn(&someClass, &SomeClass::funcAll);
    test.addMemFn(&someClass2, &SomeClass2::func2);

    return 0;
}