Welcher STL Container zum sortierten Einfügen?



  • also ca. so?

    bool EventGreater( const IEvent &*pEvt1, const IEvent &*pEvt2 )
    {
        return pEvt1->GetProcessTime() > pEvt2->GetProcessTime();
    }
    
    typedef std::priority_queue<IEvent*, std::vector<IEvent*>, &EventGreater> DelayedEventList;
    


  • Also ich habe es jetzt wie folgt gemacht:

    class CEventComparison
    {
    public:
    	bool operator()( const IEvent *pEvtLeft, const IEvent *pEvtRight ) const {
    		return pEvtLeft->GetProcessTime() > pEvtRight->GetProcessTime();
    	}
    };
    
    typedef std::priority_queue<IEvent*, std::vector<IEvent*>, CEventComparison> DelayedEventQueue;
    

    Ich bekomme nur leider den Fehler: "Fehler 1 error C2039: 'GetProcessTime': Ist kein Element von 'IEvent'", und das obwohl in meiner IEvent-Klasse ganz eindeutig steht:

    inline const float &GetProcessTime( void ) const { return m_fProcessTime; }
    

    Bin grad etwas ratlos.



  • Steht das tatsächlich in der IEvent Klasse oder in der Klasse, die IEvent implementiert? Sieht halt nach einem "Interface" aus, wo man normalerwiese keine Implementierung drin hat.



  • Nene GetProcessTime() ist in IEvent selber implementiert. Ich habe grad mal versucht bei IEvent die CEventComparison class als friend einzutragen und direkt auf den entsprechenden (privaten) Member zuzugreifen, selber Fehler...

    //EDIT:
    *Facepalm*

    #ifdef _CLIENT
    	inline const float &GetProcessTime( void ) const { return m_fProcessTime; }
    	inline void SetProcessTime( const float &time ) { m_fProcessTime = time; }
    #endif
    

    Man sollte dann natürlich die CEventComparison Class auch mit #ifdef umschließen -.-

    Vielen Dank 😉



  • Hm ohne Code nihct nachvollziehbar.

    class Event
    {
    public:
        Event(float time) : time_(time){}
        float GetProcessTime() const { return time_; }
        virtual void Fire() const = 0;
    private :
        float time_;
    };
    
    class HalloEvent : public Event
    {
    public:
        HalloEvent(float time) : Event(time){}
        void Fire() const
        {
            std::cout << "Hallo\n";
        }
    };
    
    class EventComparison
    {
    public:
        bool operator()( const Event *lh, const Event *rh ) const {
            return lh->GetProcessTime() > rh->GetProcessTime();
        }
    }; 
    
    template<typename Queue>
    void FireNext(Queue& eventQueue)
    {
        Event* nextEvent = eventQueue.top();
        // hier sollte man unbedingt noch über Ausnahmesicherheit nachdenken!
        eventQueue.pop();
        nextEvent->Fire();
        delete nextEvent;
    }
    
    int main()
    {
        typedef std::priority_queue<Event*, std::vector<Event*>, EventComparison> DelayedEventQueue;
        DelayedEventQueue queue;
        queue.push(new HalloEvent(1.0));
        while(!queue.empty())
            FireNext(queue);
    
        return 0;
    }
    


  • Danke für deine Mühe aber ich bin über den Preprocessor gestolpert (siehe oben der Post). Hat nicht jemand mal gesagt "The Preprocessor is evil" ?



  • RedPuma schrieb:

    //EDIT:
    *Facepalm*

    #ifdef _CLIENT
    	inline const float &GetProcessTime( void ) const { return m_fProcessTime; }
    	inline void SetProcessTime( const float &time ) { m_fProcessTime = time; }
    #endif
    

    Oh. Also #ifdefs innerhalb von Klassendefinition ist ganz schön pervers. Und dass der Returntyp von GetProcessTime "const float&" statt "float" ist, find' ich auch komisch.



  • Ich weis, habs grad geändert in:

    inline const float &GetProcessTime( void ) const { 
    #ifdef _CLIENT
    		return m_fProcessTime;
    #else
    		return 0.0f;
    #endif
    	}
    
    	inline void SetProcessTime( const float &time ) { 
    #ifdef _CLIENT
    		m_fProcessTime = time; 
    #endif
    	}
    


  • RedPuma schrieb:

    Ich weis, habs grad geändert in:

    Jetzt hast du es durch etwas Schlimmeres ersetzt. Als Nicht-Client kann man die Methoden zwar benutzen, aber sie bewirken nichts. Stell dir mal vor, das Makro wird versehentlich nicht mehr definiert. Ob das wohl so schnell jemand bemerkt?

    Außerdem solltest du den Wert nicht per Referenz zurückgeben. Darf man das mit dem Literal überhaupt?



  • Du hast recht. Habs wieder zurückgeändert, dann spuckt mir der Compiler wenigstens Fehler aus falls man die Methode im Server benutzen will.

    Achso was soll an "const float&" ungewöhnlich sein? Will nur unnützes Kopieren verhindern. Mag sein dass der Compiler das auch so optimieren würde aber ich gehe lieber sicher, gerade weil die Methode durch die Aufrufe innerhalb der priority_queue hunderte mal pro Sekunde benutzt wird. Und da will ich sicher sein dass alles korrekt, vorsicht Denglisch, ge-inlined wird.

    Mal ne Frage nebenbei, bei Visual Studio 2010, werden da Funktionen mit __forceinline auch im Debug-Build inlined obwohl Inlining da deaktiviert ist? Gibt son paar Sachen in meiner Mathe-Bib die ich gerne auch im Debug inlinen würde.



  • RedPuma schrieb:

    Achso was soll an "const float&" ungewöhnlich sein? Will nur unnützes Kopieren verhindern. Mag sein dass der Compiler das auch so optimieren würde aber ich gehe lieber sicher, gerade weil die Methode durch die Aufrufe innerhalb der priority_queue hunderte mal pro Sekunde benutzt wird. Und da will ich sicher sein dass alles korrekt, vorsicht Denglisch, ge-inlined wird.

    Mal ne Frage nebenbei, bei Visual Studio 2010, werden da Funktionen mit __forceinline auch im Debug-Build inlined obwohl Inlining da deaktiviert ist? Gibt son paar Sachen in meiner Mathe-Bib die ich gerne auch im Debug inlinen würde.

    Referenzen gibt es auch nicht umsonst, daher ist die Rück- bzw. Übergabe von integrierten Typen per Referenz aus Performancegründen nicht sinnvoll. Genauso wie das Benutzen von inline . Das inline Schlüsselwort solltest Du eigentlich fast nie brauchen, ausser um bei Funktionen die ODR nicht zu verletzen.
    Im Allgemeinen soltlest Du Dich entspannen und den Compiler machen lassen. Der ist im Optimieren sehr gut und weiß viel besser als Du was zu tun ist.



  • brotbernd schrieb:

    Der ist im Optimieren sehr gut und weiß viel besser als Du was zu tun ist.

    Das will ich hoffen.

    Könntest du auf die Performance bei Referenzen-Übergabe nochmal genauer eingehen?



  • RedPuma schrieb:

    brotbernd schrieb:

    Der ist im Optimieren sehr gut und weiß viel besser als Du was zu tun ist.

    Das will ich hoffen.

    Könntest du auf die Performance bei Referenzen-Übergabe nochmal genauer eingehen?

    Referenzen sind auf niedriger Ebene nichts anderes als Zeiger (sie sind C++ Syntax-Sugar um Operatorenüberladung netter implementieren zu können).

    Dh. wenn du auf einen Wert hinter einer Referenz zugreifst, muss der auch erstmal dereferenziert werden, was aber auch nur bei primitiven Typen nen Unterschied macht.

    Im Endeffekt ist es praktisch egal, gewöhn dir einfach an alles was in kein Register passt per Referenz zurückzugeben, den Rest per Value.
    Float passt super in ein Register, also ist die Rückgabe per const reference Schwachsinn.



  • Eine Referenz ist im Prinzip das gleiche wie ein Zeiger. D.h., übergibst du eine Referenz oder einen Zeiger wird da die Adresse des eigentlichen Objekts kopiert, vom Aufwand das gleiche wie ein int oder float oder anderen primitiven Typen zu kopieren. Allerdings hast du eben über einen Zeiger oder Referenz eine zusätzliche Indirektion.
    Wenn Deine Funktion vom Compiler geinlined wird, ist das eh alles egal. Da macht der Compiler sowieso was am besten ist. D.h. eine inline Funktion die eine Referenz auf ein float zurückgibt, wird wahrscheinlich am Ende einfach den Wert kopieren.
    D.h. primitive Typen immer per Wert übergeben oder zurückgeben (natürlich nicht, wenn er tatsächlich verändert werden soll). Bei Klasseninstanzen mit höherem Kopieraufwand, verwendet mann dann besser konstante Referenzen, wobei auch da der Compiler einiges machen darf (http://cpp-next.com/archive/2009/08/want-speed-pass-by-value/). Mit C++11 kommt dann noch die Möglichkeit der rvalue Referenz dazu.


Anmelden zum Antworten