【问题标题】:C++ function pointer return typeC++ 函数指针返回类型
【发布时间】:2016-09-17 18:43:47
【问题描述】:

给出的是以下类(只是标题):

class Example {

public:

    template<class C>
    Example(bool(C::*callbackFunc)(Foo&) = nullptr) : callbackFunc(callbackFunc);

    template<class C>
    ??? getCallbackFunc() const {
        return callbackFunc;
    }

private:

    // store the func ptr
    template<class C>
    bool (C::*callbackFunc)(Foo&);
};

getter getCallbackFunc() 的正确返回类型是什么?

【问题讨论】:

  • Example::callbackFunc 是函数声明,而不是变量。查找最令人头疼的解析。
  • 真的可以存会员模板吗?

标签: c++ function templates callback function-pointers


【解决方案1】:

你的问题的答案是:

bool(C::*)(Foo&)

但是,这对您没有多大帮助,因为您不能将模板变量存储在类实例中:

template<class C>
bool (C::*callbackFunc)(Foo&);

这不是一个合法的变量声明,你真的无法修复它。

callbackFunc 替换为

std::function< bool(void*, Foo&) > callbackFunc;

然后在Examplector 中编写一个函数,将成员ptr 转换为这样的函数。它涉及从void*C* 的静态转换。

获取回调函数返回:

std::function< bool(C*, Foo&) >

这是从callbackFunc 隐式转换的。

您可以通过传入C*Foo&amp; 来使用它。

【讨论】:

  • 您能展示一下Example 的ctor 应该是什么样子吗?我仍然没有让它工作。 :( C* 不知道 getCallbackFunc() 何时被调用。
  • @user &lt;C&gt; 必须以书面形式传入。很可能你有一个 XY 问题,你要求 X 的解决方案,但你真正的问题是 Y。: callbackFunc([callbackFunc](void*ptr, Foo&amp;foo)-&gt;bool{ return (static_cast&lt;C*&gt;(ptr)-&gt;*callbackFunc)(foo); }){} 或类似的。
【解决方案2】:

你的第一个问题是你不能在没有模板化整个类的情况下模板化成员变量。一旦解决了这个问题,我们就可以尝试使用The Right Left Rule 来计算getCallbackFunc 函数的返回值。我向您的构造函数添加了一个主体,因为您提供了一个 init-list(内联构造函数)。

struct Foo {};

// need to template the whole class to
// template member variables
template<class C>
class Example {

public:

    Example(bool(C::*callbackFunc)(Foo&) = nullptr)
    : callbackFunc(callbackFunc) {} // init list means this needs a body

    // use the right-left-rule 
    bool (C::*getCallbackFunc())(Foo&) {
        return callbackFunc;
    }

private:

    // store the func ptr
    bool (C::*callbackFunc)(Foo&);
};

class CallbackClass
{
public:
    bool call_me_back(Foo&) { std::cout << "Glad you called" << '\n'; return true; }
};

int main()
{
    Example<CallbackClass> eg(&CallbackClass::call_me_back);

    CallbackClass cbc; // instantiate something to call

    Foo foo; // need a foo for parameter

    // get fn pointer, dereference it and call it with cbc object
    bool return_value = (cbc.*eg.getCallbackFunc())(foo);
}

这一切都可以使用using 声明来创建一个类型别名来简化:

struct Foo {};

// create a templated type alias
template<typename C>
using CallbackType = bool(C::*)(Foo&);

// need to template the whole class to
// template member variables
template<class C>
class Example {

public:

    Example(CallbackType<C> callbackFunc = nullptr)
    : callbackFunc(callbackFunc) {} // init list means this needs a body

    // using the type alias
    CallbackType<C> getCallbackFunc() {
        return callbackFunc;
    }

private:

    // store the func ptr
    CallbackType<C> callbackFunc;
};

class CallbackClass
{
public:
    bool call_me_back(Foo&) { std::cout << "Glad you called" << '\n'; return true; }
};

int main()
{
    Example<CallbackClass> eg(&CallbackClass::call_me_back);

    CallbackClass cbc; // instantiate something to call

    Foo foo; // need a foo for parameter

    // get fn pointer
    CallbackType<CallbackClass> cb = eg.getCallbackFunc();

    // dereference it and call it with cbc object
    bool return_value = (cbc.*cb)(foo);
}

【讨论】:

    猜你喜欢
    • 2014-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-04
    • 1970-01-01
    • 2021-05-30
    • 2015-04-18
    • 1970-01-01
    相关资源
    最近更新 更多