0

Win32APIとC++標準ライブラリを使用するWindowクラスライブラリを作成することを考えてい
ます。また、ウィンドウメッセージを処理するシグナル/スロット機能を追加したいと思います。

using namespace std;
using namespace boost::signals2;
typedef signal<void (Window*, EventArgs*)> WndEvent; 

class EventArgs { public: HWND hWnd; WPARAM wParam; LPARAM lParam; };

class Window {
    protected: unordered_map<UINT, WndMsg*> msgMap;
    public: void addMsgHandler(UINT msg, void (*handler)(Window*, EventArgs*)) {
        auto iter=msgMap.find(msg);
        if(iter==msgMap.end()) {
            WndEvent* newEvent = new WndEvent();
            newEvent->connect(handler);
            msgMap.insert(make_pair(msg, newEvent));
        }
        else iter->second->connect(handler);
    }

    private: LRESULT wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lparam) {
        for(auto iter=msgMap.begin(); iter!=msgMap.end(); iter++)
            iter->second->();
    }
};

そのライブラリを使用する場合:

class Form : public Window {
    void initialize() {// add here pair of 'message' and 'corresponding handler'
        addMsgHandler(WM_LBUTTONUP, boost::bind(&Form::onLButtonUp, this, _1, _2));
        ...
    }
    void onLButtonUp(Window* sender, EventArgs* e) { // event handler
        wchar_t buf[1000]; 
        wsprintf(buf, L"(%d, %d) clicked", GET_X_LPARAM(e->lParam), GET_Y_LPARAM(e->lParam));
        MessageBox(0, buf, L"", MB_OK);
    }
}

ここでの問題は、onLButtonUpがクラスメンバー関数であるため、署名が一致しないことです。
だから私はboost::bindを使おうとしました、そして私はこのようなコンパイルエラーを受け取りました:

 Window::addMsgHandler': cannot convert parameter 2 'boost::_bi::bind_t<R,F,L>' to 'void (__cdecl *)(Window *,EventArgs *)'

つまり、addMsgHandler()のシグネチャを(単純な関数ポインタからブースト関数オブジェクトに)変更する必要がありますが、

渡されるデータ型(非常に長いテンプレートパラメータを含む)を決定できません。

コンパイルエラーメッセージには

R=void,            
F=boost::_mfi::mf2<void,Form,Window *,EventArgs *>,1>                           
L=boost::_bi::list3<boost::_bi::value<Form*>,boost::arg<1>,boost::arg<2>>                

さらに、他の多くのクラスはクラスWindowから派生するため、クラスWindowを定義するときにテンプレートタイプを知ることができません。

boost.bindオブジェクトを関数パラメーターとして渡す適切な方法はありますか?

4

1 に答える 1

0

次のように定義します。

void addMsgHandler(UINT msg, const function<void(Window* , EventArgs*)>& slot);

またはこのようにさえ:

void addMsgHandler(UINT msg, const WndEvent::slot_type &slot);

これで、この関数を呼び出すとき、パラメーターはタイプとslotの2つの引数を受け入れる「呼び出し可能」である必要があり、、、、を使用するか、適切なraw関数ptrを渡すだけでそのようなスロットを作成できます。Window *EventArgs *mem_fnboost::bindstd::bind

于 2012-10-03T11:06:42.413 に答える