문제

말을 디자인하고 있었 C++윈도우 라이브러리입니다.그것은 또는 제공하지 않을 수도 있습니다 콜백 API 지만,필요를 제공하는 폴링 API 을 촉진하는 기능적인 스타일의 프로그래밍입니다.

어떻게 투표 API 처럼 보이나요?

몇 가지 옵션

SDL 스타일

struct Event {
    enum { MousePress, KeyPress } type;
    union {
        struct { Point pos; MouseButton b; } mousePress;
        struct { Modifiers mods; char key; } keyPress;
    };
};
void userCode() {
    for(;;) {
        Event e; if(pollEvent(&e)) {
            switch(e.type) {
                case MousePress: cout<<event.mousePress.pos.x; break; // not typesafe
                case KeyPress: cout<<event.keyPress.key; break;
            }
        }
    }
}

주 스타일

struct Input {
    enum { Mouse, Keyboard, Nothing } whatChanged;
    MouseButtonsBitfield pressedButtons;
    bool keysPressed[keyCount];
};
void userCode() {
    for(;;) {
        Input in = pollInput();
        switch(in.whatChanged) {
            // typesafe yay
            case Mouse: cout << "is LMB pressed? " << bool(in.pressedButtons&LeftButton); break;
            case Keyboard: cout << "is A pressed? " << in.keysPressed['A']; break;
        }
    }
}

재미있는 기능을 의사는 C++스타일

struct Event {
    // transforms listener by notifying it of event,
    // returns transormed listener. nondestructive.
    template<class Listener> // sadly invalid, templates can't be virtual.
                                              // a solution is to make Listener the base
                                              // of a hierarchy and make Listener::handle virtual
                                              // but then we're forced to use imperative style
    virtual Listener transform(Listener const&) =0;
};
struct MousePress : Event { // yay we're extensible via inheritance
    template<class Listener>
    virtual Listener transform(Listener const& listener) {
        return listener.handle(*this); // calls the MousePress overload
    }
    Point pos; MouseButton b;
};
struct KeyPress : Event {
    template<class Listener>
    virtual Listener transform(Listener const& listener) {
        return listener.handle(*this); // calls the KeyPress overload
    }
    Modifiers mods; char key;
};
struct NoEvent : Event {
    template<class Listener>
    virtual Listener transform(Listener const& listener) {
        return listener.handle(*this);
    }
};
struct UserWidget {
    UserWidget handle(NoEvent) {
        return UserWidget();
    }
    UserWidget handle(MousePress p) {
        return (UserWidget) { string("pressed at")+lex_cast<string>(p.pos)) };
    }
    UserWidget handle(KeyPress k) {
        return (UserWidget) { string("pressed key=")+lex_cast<string>(k.key)) };
    }
    string pendingOutput;
};
void userTick(UserWidget const& w) {
    cout<<w.pendingOutput;
    userTick(pollEvent().transform(w));
}
void userCode() {
    userTick(UserWidget());
}

에 대한 답변 다른 언어는 C++보다 확인을 경우,그들이 제공하는 흥미로운 통찰력.

없음에 대한 의견 캡슐에 넣기 하시기 바랍니다-예 공용 필드 정말로 접근,내가 왼쪽으니다.

도움이 되었습니까?

해결책

당신의 질문에 대답게,내가 선호하는 단순함의"SDL 스타일 코드"를 참조하십시오.주로하기 때문에 조금 더 복잡한 상태"스타일"폐기물 메모리 구 당신이 절대적으로 아무것도(아래 참고),그리고 재귀에서 고문"기능적 의사-C++"스타일이 오버플로어 스택에서 몇 밀리초 단위입니다.

상태"스타일":귀하의"형식이 안전한 예에서는"상태"스타일"코드를 조금 부당하다.당신은 여전히 결정하는 구성원에 따라 액세스 switch 다른 회원,그래서 코드가 모든 동일한 약점는"SDL 스타일로는"코드가 어떠한 실수는 할 수 있으로 SDL 스타일 코드는 해석하는 메모리로서 잘못된 유형,당신은 것을 똑같이 나쁜 실수의 액세스는 초기화되지 않은 구성원 상태와 스타일의 코드입니다.

"기능적 의사-C++스타일":지금 당신이 어딘가에,상속 다른 이벤트 유형을 기초에서는 이벤트 유형입니다.분명히 어리석은 재귀의 요구가 반복,그리고 몇 가지 작은 것들을 정리(나는 당신의 3 가지 방법을 이름 transform()UserWidgethandle();나는 당신이 문제를 해결할 수 있는지 없는 템플릿 가상 방법을 사용 합니다.기능 또는 이와 유사한).내 생각에 이 방법은 잠재적인,하지만 내가 선호하는 단순함의 SDL 스타일입니다.

그러나 더 근본적으로:나의 질문에 대한 필요 투표 인터페이스입니다.이 있는 이유 pollEvent() 차단할 수 없습니다?그대로,모든 3 코드 세그먼트는 불타는 CPU 시간이 아무것도 하지 않 시간의 99.99%.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top