【问题标题】:implement function object bind without using c++11 [duplicate]不使用c ++ 11实现函数对象绑定[重复]
【发布时间】:2019-05-16 12:13:30
【问题描述】:

我正在尝试实现自己的函数对象类和绑定函数(只需要包装2个参数的成员函数)。我被限制使用 GCC 4.4.6 并且 c++0x 不是一个选项。

我的代码如下。它不会编译。

#pragma once

namespace utils
{

template<class>
class CFunction;

template<class TRet, class Arg1, class Arg2>
class CFunction<TRet(Arg1, Arg2)>
{
public:
    typedef TRet (*FuncPtr) (void*, Arg1, Arg2);
    void* m_pObj;
    FuncPtr m_FuncPtr;

    TRet operator()(Arg1 arg1, Arg2 arg2)
    {
        return m_FuncPtr(arg1, arg2);
    }

    template <class TObj, TRet (TObj::*TMemFunc)(Arg1, Arg2)>
    static CFunction Create(TObj* pObj)
    {
        CFunction Ret;
        Ret.m_pObj = (void*)pObj;
        Ret.m_FuncPtr = &Caller<TObj, TMemFunc>;
        return Ret;
    }
private:
    template<class TObj, TRet (TObj::*TMemFunc)(Arg1, Arg2)>
    static TRet Caller(void* obj, Arg1 arg1, Arg2 arg2)
    {
        TObj* pObj = static_cast<TObj*>(obj);
        return (pObj->*TMemFunc)(arg1, arg2);
    }
};


template<class TRet, class TClass, class Arg1, class Arg2>
CFunction<TRet(Arg1, Arg2)> Bind(TRet (TClass::*func)(Arg1, Arg2), TClass *pObj)
{
    return CFunction<TRet(Arg1, Arg2)>::Create<TClass, func>();
}

} // end of namespace utils

编译报告

Functional.h: In function ‘utils::CFunction<TRet(Arg1, Arg2)> utils::Bind(TRet (TClass::*)(Arg1, Arg2), TClass*)’:
Functional.h:48: error: expected primary-expression before ‘,’ token
Functional.h:48: error: expected primary-expression before ‘)’ token

谁能告诉我代码有什么问题以及如何使它工作


在解决了@Vittorio 和@MSAlters 提到的问题之后。我得到了新的编译错误。

固定代码

#include <iostream>

namespace utils
{

template<class>
class CFunction;

template<class TRet, class Arg1, class Arg2>
class CFunction<TRet(Arg1, Arg2)>
{
public:
    typedef TRet (*FuncPtr) (void*, Arg1, Arg2);
    void* m_pObj;
    FuncPtr m_FuncPtr;

    TRet operator()(Arg1 arg1, Arg2 arg2)
    {
        return m_FuncPtr(m_pObj, arg1, arg2);
    }

    template <class TObj, TRet (TObj::*TMemFunc)(Arg1, Arg2)>
    static CFunction Create(TObj* pObj)
    {
        CFunction Ret;
        Ret.m_pObj = (void*)pObj;
        Ret.m_FuncPtr = &Caller<TObj, TMemFunc>;
        return Ret;
    }
private:
    template<class TObj, TRet (TObj::*TMemFunc)(Arg1, Arg2)>
    static TRet Caller(void* obj, Arg1 arg1, Arg2 arg2)
    {
        TObj* pObj = static_cast<TObj*>(obj);
        return (pObj->*TMemFunc)(arg1, arg2);
    }
};


template<class TRet, class TClass, class Arg1, class Arg2>
CFunction<TRet(Arg1, Arg2)> Bind(TRet (TClass::*func)(Arg1, Arg2), TClass *pObj)
{
    return CFunction<TRet(Arg1, Arg2)>::template Create<TClass, func>(pObj);
}

} // end of namespace utils

class TestLogic
{
public:
  bool Test(std::string& str, double d) {
     std::cout << str << ",  " << d << std::endl;
     return true;
  }
};

int main(int argc, const char **argv) {
    TestLogic testObj;
    utils::CFunction<bool(std::string&, double)> f = utils::Bind(&TestLogic::Test, &testObj);
    std::string str("hello");
    f(str, -1.0);
}

新错误:

prog.cc: In function 'utils::CFunction<TRet(Arg1, Arg2)> utils::Bind(TRet (TClass::*)(Arg1, Arg2), TClass*) [with TRet = bool, TClass = TestLogic, Arg1 = std::string&, Arg2 = double]':
prog.cc:59:   instantiated from here
prog.cc:43: error: 'func' is not a valid template argument for type 'bool (TestLogic::*)(std::string&, double)'
prog.cc:43: error: it must be a pointer-to-member of the form `&X::Y'
prog.cc:43: error: no matching function for call to 'utils::CFunction<bool(std::string&, double)>::Create(TestLogic*&)'

谁能帮我解决这个问题?

你可以运行这段代码enter link description here

【问题讨论】:

    标签: c++ function templates


    【解决方案1】:

    您需要在Bind 中使用template 关键字作为消歧符:

    return CFunction<TRet(Arg1, Arg2)>::template Create<TClass, func>();
    //                                  ^~~~~~~~
    

    这是因为Create 是一个从属名称,编译器不知道您是在尝试调用模板函数还是将其与TClass 进行比较。有关该主题的更多阅读:Where and why do I have to put the "template" and "typename" keywords?

    【讨论】:

    • 另外,Create 需要一个 TObj*,但它是用一个空参数列表调用的。由于名称查找失败,因此尚未发现此错误。
    • @MSalters 是的。我在修复 Vittorio 提出的名称查找问题后遇到了这个问题。但是我的代码仍然无法编译。我修改了问题。你能帮我解决这个问题吗?非常感谢
    • 幸运的是,这是微不足道的。您正在使用运行时变量 func 作为编译时参数 Create&lt;TClass, func&gt;。这不是 C++ 的工作方式。我建议您查看较旧的 Boost 版本(C++ 11 之前,所以 1.46 或类似版本)。 C++11 bind 来自 Boost。
    • @MSalters 好的。我昨晚实际上试图阅读Boost绑定版本。但是刚开始就停了。模板对我来说真的是个怪物。看来我得重新捡起来了。 v_v。再次,非常感谢!
    • @FeiyuChen:是个怪物。这就是你想要它的原因;否则你需要自己发明。 C++11 不是偶然的侥幸。它旨在使 Boost 和类似的库更易于编写。
    猜你喜欢
    • 2023-01-26
    • 1970-01-01
    • 1970-01-01
    • 2013-07-27
    • 2012-09-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-11
    相关资源
    最近更新 更多