Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ function pointer return type

Given is the following class (just the header):

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

What is the correct return type of the getter getCallbackFunc()?

like image 443
user1056903 Avatar asked Sep 17 '16 18:09

user1056903


2 Answers

The answer to your question is:

bool(C::*)(Foo&)

However, this won't help you much, as you cannot store a template variable in a class instance:

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

That is not a legal variable declaration, and you really cannot fix it.

Replace callbackFunc with

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

Then in Example ctor write a function that converts the member ptr into such a function. It involves a static cast fromvoid* to C*.

Get callback func returns:

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

which is implicitly-converible-to from callbackFunc.

You use it by passing C* in and the Foo&.

like image 120
Yakk - Adam Nevraumont Avatar answered Sep 29 '22 23:09

Yakk - Adam Nevraumont


Your first problem is you can't have templated member variables without temlating the entire class. Once that's fixed we can try to figure out the return value of your getCallbackFunc function using The Right Left Rule. I added a body to your constructor because you provided an init-list (inline constructor).

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

This can all be simplified somewhat using the using declaration to create a type alias:

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);
}
like image 24
Galik Avatar answered Sep 30 '22 01:09

Galik