static inline Funktionstyp



  • Guten Abend,

    ich habe einen Funktionstyp in einer Klasse. Die einer solchen Variablen übergebene Funktion wird innerhalb meiner Klasse aufgerufen. Ich möchte jedoch erzwingen, dass diese Funktion an den Ort des Aufrufs innerhalb der Klasse kopiert wird und kein call gemacht wird.

    Inwiefern ist das möglich? (Compiler: MSVC 9.0).

    class Klasse
    {
    private:
         typedef int (FUNCTION)(void*, void*, void*);
    
    public:
         FUNCTION function;
    
         void tu_was() 
         {
              for( int i = 0; i < EXTREM OFT; i++ )
                   this->function(NULL, NULL, NULL);
         }
    };
    

    Normalerweise deklariere ich eine Funktion dafür mit "static inline". Damit der Compiler a) genau weiß wo der Code überall verwendet wird und b) er daher definitiv die Funktion NICHT anlegen muss, sondern immer an den Ort seiner Verwendung kopieren kann.

    Ich möchte genau das über den Umweg der Funktionstyp-Variablen erreichen ...



  • Damit kein Aufruf stattfindet und der Code inline gemacht werden kann, muss zur Kompilierzeit klar sein, um welche Funktion es sich handelt. Dadurch, dass du dir die Flexibilität von Funktionszeigern erkaufst (du kannst nacheinander unterschiedliche Funktionen mit dieser Signatur aufrufen und mit dem Funktionszeiger fast wie mit normalen Daten umgehen), ist jene Information möglicherweise erst zur Laufzeit bekannt, was eine Optimierung verhindert.

    Allerdings ist der MSVC++-Compiler recht gut im Optimieren. Wenn der Aufruf zur Kompilierzeit einigermassen transparent ist, kann er dies wahrscheinlich erkennen. Ansonsten kannst du einen Funktor nehmen, da bist du allerdings wieder an die statische Natur von Templates gebunden.



  • Nexus schrieb:

    Allerdings ist der MSVC++-Compiler recht gut im Optimieren. Wenn der Aufruf zur Kompilierzeit einigermassen transparent ist, kann er dies wahrscheinlich erkennen. Ansonsten kannst du einen Funktor nehmen, da bist du allerdings wieder an die statische Natur von Templates gebunden.

    Danke für deine Antwort. Leider erkennt er dies nicht; dass konnte ich bereits dem Assembly-Listing entnehmen.

    Eigentlich muss die Funktion ein einziges mal zugewiesen werden. Ich brauche nicht die Option innerhalb einer Instanz diese Funktion zu wechseln.



  • Dann mach aus deiner Funktion eine template-Funktion...



  • Eine Möglichkeit ist wie gesagt ein Funktor. Dazu machst du deine Klasse zu einem Template, bei dem du den Typ des Funktionsobjekts angeben kannst. Das lohnt sich vor allem, wenn letzteres einen eigenen Status hat; geht es nur um ein bestimmtes Verhalten, kann eine Policy-Klasse sinnvoller sein.

    template <class Function>
    class test
    {
        public:
            // initialisiere m_func im Konstruktor
            test(/* irgendwas */);
    
            void do_something()
            {
                m_func(0, 0, 0);
            }
    
        private:
            Function m_func;
    };
    
    struct functor
    {
        void operator() (void* a, void* b, void* c) const;
    };
    
    test<functor> test_obj;
    

    Oder du machst es mit einer Policy-Klasse, von der keine Instanz angelegt werden muss. Das kann hier irgendeine Klasse sein, die eine öffentliche statische Memberfunktion mit dem Namen perform_action() und einer kompatiblen Signatur bereitstellt. Dem Klassentemplate test übergibst du dann das gewünschte Verhalten mittels Template-Argument.

    template <class Behaviour>
    class test
    {
        public:
            void do_something()
            {
                Behaviour::perform_action(0, 0, 0);
            }
    };
    
    struct my_behaviour
    {
        static void perform_action(void* a, void* b, void* c);
    };
    
    test<my_behaviour> test_obj;
    


  • Th69 schrieb:

    Dann mach aus deiner Funktion eine template-Funktion...

    Hab ich jetzt auch so gemacht.



  • FrEEzE2046 schrieb:

    Hab ich jetzt auch so gemacht.

    Wenn die Instanz über die ganze Zeit die gleiche Funktion aufrufen soll, finde ich ein Klassentemplate sinnvoller als ein Memberfunktionstemplate, da du ansonsten nur die ganze Zeit unnötig Typen angibst.


Anmelden zum Antworten