2016-09-17 4 views
4

Gegeben ist die folgende Klasse (nur der Header):C++ Funktionszeiger Rückgabetyp

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

Was ist der korrekte Rückgabetyp des Getter getCallbackFunc()?

+1

'Beispiel :: callbackFunc' ist eine Funktionsdeklaration, keine Variable. Schau dir die ärgsten Pars an. – Rakete1111

+0

Können Sie wirklich eine Mitgliedervorlage speichern? –

Antwort

3

Die Antwort auf Ihre Frage ist:

bool(C::*)(Foo&) 

Doch dies wird nicht viel helfen, da Sie kein Template-Variable in einer Klasseninstanz speichern können:

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

, das nicht eine rechtliche Variablendeklaration, und Sie können es wirklich nicht beheben.

Ersetzen callbackFunc mit

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

dann in Example Ctor eine Funktion schreiben, daß das Element ptr in eine solche Funktion umwandelt. Es handelt sich um ein statisches Modell von void* bis C*.

Get Rückruf func kehrt:

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

, die implizit-Converible-to von callbackFunc.

Sie verwenden es, indem Sie C* in und die Foo& übergeben.

+0

Können Sie zeigen, wie der ctor von '' Beispiel'' aussehen muss? Ich bekomme es immer noch nicht zur Arbeit. :('' 'C *' 'ist nicht bekannt, wenn getCallbackFunc() aufgerufen wird. – user1056903

+0

@user' 'muss wie geschrieben übergeben werden. Wahrscheinlich haben Sie ein XY-Problem, wo Sie nach einer Lösung für X, aber Ihre echte gefragt Problem ist Y. ': callbackFunc ([callbackFunc] (void * ptr, Foo & foo) -> bool {return (statischer_cast (ptr) -> * callbackFunc) (foo);}) {}' oder sowas. – Yakk

0

Ihr erstes Problem besteht darin, dass Sie keine Membervariablen in einem Template erstellen können, ohne die gesamte Klasse zu templatieren. Sobald das behoben ist, können wir versuchen, den Rückgabewert Ihrer getCallbackFunc Funktion mit The Right Left Rule herauszufinden. Ich habe Ihrem Konstruktor einen Body hinzugefügt, weil Sie eine Init-Liste (Inline-Konstruktor) angegeben haben.

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

Dies kann alles etwas vereinfacht werden, um die using Erklärung unter Verwendung eines Alias ​​Typ zu erstellen:

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