2016-09-17 12 views
4

では、以下のクラス(単にヘッダ)である:C++の関数ポインタの戻り値の型

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

ゲッターgetCallbackFunc()の正しい戻り値の型は何ですか?

+1

'例:: callbackFunc'は、関数宣言ではなく、可変です。最も厄介な解析を見てください。 – Rakete1111

+0

本当にメンバーテンプレートを保存できますか? –

答えて

3

あなたの質問への答えは:ないです

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

bool(C::*)(Foo&) 

あなたはクラスのインスタンスでテンプレート変数を格納することはできませんしかし、これは、ずっとあなたを助けにはなりません法律上の変数宣言であり、本当にそれを修正することはできません。

Exampleに続い

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

callbackFuncを交換CTORそのような関数に部材PTRを変換する関数を書きます。それには、void*からC*までの静的キャストが関係します。

取得コールバックFUNC戻っ:

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

暗黙的-converible-へcallbackFuncからです。

C*Foo&を渡して使用します。

+0

'' Example''のctorがどのように見えるかを表示できますか?私はまだそれを動作させることはありません。 – user1056903

+0

@user ' 'は書かれている通りに渡されなければなりません。あなたはXに解決策を求めたところでXYの問題を抱えていますか? callbackFunc(void * ptr、Foo&foo) - > bool {return(static_cast (ptr) - > * callbackFunc(foo);}){} 'またはそれ以上のもの。 – Yakk

0

最初の問題は、クラス全体をテンプレート化することなくテンプレート化されたメンバ変数を持つことができないことです。それが確定したら、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); 
} 
関連する問題