dynamik bei funktionsaufrufen



  • nehmen wir an wir haben 500 funktionen
    ob funktionspointer oder nicht sei dahingestellt

    nun haben wir noch einen array variabler grösse, der unterschiedliche datentypen enthält

    array[DataObj*];

    mit
    array[0]->GetDataType();
    könnten wir z.b. prüfen obs n long/double/string/memblock etc. is

    die frage is nun... kann ich folgenden code irgendwie abkürzen

    switch ( functionid )
    {
    case 0:
      func0( array[0], array[1], array[2] );
    case 1:
      func1( array[0] );
    ...
    ...
    case 498:
      func498( array[0], array[1] );
    case 499:
      func499( array[0], array[1], array[2], array[3] );
    }
    

    quasi irgendwie die funktionen dynamisch aufrufen

    das ganze is teil von ner art remoteinterface in dem ein lokaler rechner aufgerufene funktionen eines standardinterfaces der software zu einem remoterechner zur bearbeitung schickt und das ergebnis zurückliefert als hätte ers lokal berechnet



  • *schieb*



  • in eine std::map<id, funktion> packen.

    dann machst du nur noch

    map[id](juhu);
    zum aufrufen der passenden funktion

    dazu muesstest du aber die funktionen angleichen. dazu zB eine struktur als parameter uebergeben wo die passenden werte drinnen stehen.



  • ne die funktionen müssten gleich bleiben
    ansonsten wär der arbeitsaufwand der selbe weil ich jede funktion einzeln anpassen muss



  • Sovok schrieb:

    ne die funktionen müssten gleich bleiben
    ansonsten wär der arbeitsaufwand der selbe weil ich jede funktion einzeln anpassen muss

    vielleicht kannste variable parameterlisten einsetzen und dann die function-id mitgeben. guckst du: http://www.fh-fulda.de/~klingebiel/c-stdlib/stdarg.htm
    ...aber wenn sich für jede function-id die bearbeiteung komplett unterscheidet, dann musste wohl oder übel für jede einen eigenen code-abschnitt haben (kommt also auf das gleiche raus). musst halt sehen dass du so viele gemeinsamkeiten wie möglich findest und die dann in funktionen auslagerst



  • gibts bei der variante ne möglichkeit rauszufinden, wieviele argumente die funktion hat und ob der aufruf von va_arg erfolgreich war?

    int val = va_arg( list, int);
    //val is nu == 0
    //heisst das 0 wurde übergeben oder der aufruf war ned erfolgreich? :-/
    

    habs mir mal genauer angeschaut
    list is ja einfach n array mit pointern auf die übergebenen argumente
    so wies ausschaut is da kein hauch von typensicherheit vorhanden
    wenn ich nen char* übergebe und mit int val = va_arg( list, int); abfrage,
    steht in val die adresse des char pointers



  • Sovok schrieb:

    gibts bei der variante ne möglichkeit rauszufinden, wieviele argumente die funktion hat und ob der aufruf von va_arg erfolgreich war?

    ich glaub nicht, aber man kann ja z.b. die anzahl der argumente als erstes argument angeben



  • Man sollte aber Bedenken, dass das Verhalten der Ellipse mit Objekten nicht definiert ist.



  • Wie wär's denn hiermit:

    // Ueberladungen fuer vlt. 0-10 Argumente...
    template <typename ReturnT, typename Par1T, typename Par2T>
    size_t numArgs( ReturnT (*)(Par1T, Par2T) )
    {
      return 2;
    }
    
    template <typename ReturnT, typename Par1T, typename Par2T, typename Par3T>
    size_t numArgs( ReturnT (*)(Par1T, Par2T, Par3T) )
    {
      return 3;
    }
    
    // dto, 0-10 oder so
    template <typename FunctionPtrT, typename Par1T, typename Par2T>
    void callhelper2( FunctionPtrT f, Par1T p1, Par2T p2 )
    {
      f(p1, p2);
    }
    
    template <typename FunctionPtrT, typename Par1T, typename Par2T, typename Par3T>
    void callhelper3( FunctionPtrT f, Par1T p1, Par2T p2, Par3T p3 )
    {
      f(p1, p2, p3);
    }
    
    struct FunctionWrapperBase
    {
      virtual void call( array& args ) = 0;
      virtual ~FunctionWrapperBase() { }
    };
    
    template<typename FunctionPtrT>
    class FunctionWrapper : public FunctionWrapperBase
    {
    public:
      FunctionWrapper( FunctionPtrT funptr ) : funptr(funptr) { }
      void call( array& args )
      {
        switch(numArgs(funptr)) {
        // dto, 0-irgendwas
        case 2:
          callhelper2(funptr, toType(args[0]), toType(args[1]));
          break;
        case 3:
          callhelper3(funptr, toType(args[0]), toType(args[1]), toType(args[2]));
          break;
        };
      }
    private:
      FunctionPtrT  funptr;
    };
    // ...
    
    typedef std::map<id_t, FunctionWrapperBase*> FunctionMap;
    FunctionMap myfunctions;
    // ...
    
    myfunctions[id]->call(myargs);
    

    Könntest auch verschiedene Wrapper basteln und dir von einer Factory den richtigen erzeugen lassen um das switch statement loszuwerden.


Anmelden zum Antworten