Probleme bei Var Args: sinnlose Werte bei Übergabe



  • Dann müsste ich ja 10 Templateklassen erstellen, die jeweils 1, 2, 3, 4, 5, 6, 7, 8, 9 oder 10 Parameter annehmen kann. Sowas nenne ich weder elegant noch komfortabel.

    Gruß



  • theliquidwave schrieb:

    Aber das iCount ist schon richtig.

    nein, siehe va_start(). Da musst du das letzte Argument vor den "..." übergeben.


  • Administrator

    theliquidwave schrieb:

    Ich kann nicht verstehen was daran gefährlich ist, solange man es richtig anwendet.

    Haargenau! Wieso machst du es dann nicht?

    theliquidwave schrieb:

    Aber das iCount ist schon richtig. Denn es gibt ja für jeden erwarteten Parameter der Python Funktion zwei Werte, die ich annehme. Einmal der Typ des erwarteten Parameters (z.B. 3 aka String) und dann die Adresse zur Variable. Also muss man die Anzahl der Parameter mal 2 nehmen. iNeeded gibt nur an, dass z.B. zwei Parameter benötigt, und z.B. 0 weitere Optional sind (iOptional).

    Lies mal die Dokumentation, was als zweites Argument von va_start benötigt wird:
    http://www.cplusplus.com/reference/clibrary/cstdarg/va_start/

    Das ist nur einer der vielen Gründe, wieso dies eine schlechte Lösung ist. Du hast es grad selber bewiesen 😉

    theliquidwave schrieb:

    Dann müsste ich ja 10 Templateklassen erstellen, die jeweils 1, 2, 3, 4, 5, 6, 7, 8, 9 oder 10 Parameter annehmen kann. Sowas nenne ich weder elegant noch komfortabel.

    Mit Makros aber durchaus machbar. Und zukünftig dann durch variadic Templates ersetzbar.

    Grüssli



  • OMG!
    Diese Seite habe ich mir mindestens 3x durchgelesen, aber das habe ich immer falsch interpretiert -.-

    Danke!



  • Dravere schrieb:

    Und zukünftig dann durch variadic Templates ersetzbar.

    Wenn dein Compiler Variadic Templates nicht unterstützt könntest du zb. auf gcc umsteigen, dieser Compiliert folgenden code einwandfrei:

    template<class Type>
    void Print( Type Arg )
    {
        std::cout<< Arg <<"\n" ;
    }
    
    template<class Type, class...Types>
    typename
    std::enable_if< sizeof...(Types)<10 , void > // Maximal 10 args
    ::type Print( Type Arg , Types...Args )
    {
        std::cout<< Arg <<"\n" ;
        Print(Args...); // Rekrusion
    }
    
    int main()
    {
        Print("eins",2,3,4,5);
    }
    

    Gruss
    Speed


  • Administrator

    Speed schrieb:

    Wenn dein Compiler Variadic Templates nicht unterstützt könntest du zb. auf gcc umsteigen, ...

    Und so ein Umstieg ist einfach und problemlos möglich 🤡
    Wenn wir es zudem ganz genau nehmen, sind variadic Templates noch gar nicht als Standard definiert 😉

    Also bevor man vorschnell den Kompiler wechselt und die ganze Entwicklungsumgebung womöglich gleich mit, sollte man sich überlegen, ob ein bis zwei Jahre zusätzliches Warten, vielleicht nicht besser wäre.

    Grüssli



  • Dravere schrieb:

    Speed schrieb:

    Wenn dein Compiler Variadic Templates nicht unterstützt könntest du zb. auf gcc umsteigen, ...

    Und so ein Umstieg ist einfach und problemlos möglich 🤡
    Wenn wir es zudem ganz genau nehmen, sind variadic Templates noch gar nicht als Standard definiert 😉

    Also bevor man vorschnell den Kompiler wechselt und die ganze Entwicklungsumgebung womöglich gleich mit, sollte man sich überlegen, ob ein bis zwei Jahre zusätzliches Warten, vielleicht nicht besser wäre.

    Grüssli

    Sind Variadic Templates nicht im C++09-Standart eingeführt worden?
    Glaubst du das Compilerhersteller-die es Bereits eingeführt haben das anschließend wieder, raus nehmen werden?
    Naja wie auch immer...

    Meistens ist es dem Kunden egal, Wie Man etwas macht - er will Ergebnisse sehen.
    Und mit Konstrukten wie diesen kann man m.E. viel schneller und effizienter Programmieren.
    Wenn der Trendsteller nicht in all zu großen Gruppen und das Projekt nicht weit fortgeschritten(Leider ist der meiste Code nicht von Compiler zu Compiler portabel, besonders wenns sich um GUI-IDEs handelt) ist, meine ich, dass sich ein Umstieg Lohnt. Deswegen versuche ich stets, solche "Compiler-features" auszunutzen...

    Gruss
    Speed

    Edit: wieso wird Standart Zensiert?
    Edit2 : wieso macht er es lowwercase?
    Edit3 : @Dravere : wie hast du es hingekriegt?



  • Standard

    Einfach richtig schreiben, dann wirst du auch nicht zensiert.


  • Administrator

    Speed schrieb:

    Sind Variadic Templates nicht im C++09-stan**** eingeführt worden?

    Witzbold, C++0x ist noch nicht verabschiedet. Wenn alles gut geht, dann können wir den Standard Ende 2011 erwarten. Ja, variadic Templates werden mit sehr hoher Wahrscheinlichkeit drin sein, wüsste jedenfalls nicht, wieso man sie aus dem aktuellen Draft rausnehmen sollte, aber man weiss ja nie 😉

    Spee schrieb:

    Wenn der Trendsteller nicht in all zu großen Gruppen und das Projekt nicht weit fortgeschritten(Leider ist der meiste Code nicht von Compiler zu Compiler portabel, besonders wenns sich um GUI-IDEs handelt) ist, meine ich, dass sich ein Umstieg Lohnt. Deswegen versuche ich stets, solche "Compiler-features" auszunutzen...

    1. Trendsteller? (wahrscheinlich Thread-Ersteller gemeint?) 😃
    2. Man kann Code so programmieren, dass er vollkommen protabel ist. Da sind auch GUIs gar kein Problem, man muss sich nur entsprechender Frameworks bedienen.
    3. "Compiler-Features" sollte man mit Vorsicht geniessen. Sie machen den Code eben unportabel. Zum Teil sogar zwischen Kompilerversionen des gleichen Herstellers. Der Standard dagegen ändert sich nur sehr selten und bleibt meistens rückwärtskompatibel.
    4. Du vergisst irgendwie, dass man beim Wechsel des Kompilers oft auch noch andere Dinge wechseln muss. Zum Beispiel Debugger, Linker, Build-Tools, IDE usw.
    Auch sollte man nicht unterschätzen, was man an Know-How verliert, wenn man diese Umstellung durchführt.

    Also nur wegen variadic Templates den Kompiler zu wechseln, halte ich für grob verkehrt. In einem kleinen privaten Projekt, mag dies vielleicht noch möglich sein, in einer Firma aber definitiv ein absolutes No-go. Ich würde es aber nicht mal einem privaten empfehlen, nur wegen variadic Templates einen anderen Kompiler zu nehmen, zumal es sowieso noch nicht Standard ist.

    Speed schrieb:

    Edit: wieso wird stan**** Zensiert?
    Edit2 : wieso macht er es lowwercase?
    Edit3 : @Dravere : wie hast du es hingekriegt?

    Schau mal im Duden nach, wie man Standard schreibt.

    Grüssli



  • ich würde jetzt zwar auch nicht den compiler wechseln weil einem hier gesagt wird das va_arg() "böse" ist, aber...

    Dravere schrieb:

    Auch sollte man nicht unterschätzen, was man an Know-How verliert, wenn man diese Umstellung durchführt.

    das sollte wohl nicht das problem sein 🙄



  • theliquidwave schrieb:

    Die erwarteten Parameter sind wie gesagt variabel und ich kann deshalb nicht einfach einen Vektor nehmen. Und da sie zur Compilezeit feststehen ist das auch gar nicht nötig.

    Irgendwie sieht der Code so aus, als ob immer ein PyObject draus wird.


  • Administrator

    DrGreenthumb schrieb:

    Dravere schrieb:

    Auch sollte man nicht unterschätzen, was man an Know-How verliert, wenn man diese Umstellung durchführt.

    das sollte wohl nicht das problem sein 🙄

    Dann bist du der Meinung, dass wenn jemand sehr gut mit dem MSVC Debugger umgehen kann, er sofort auch ohne Probleme mit dem GDB umgehen kann?
    Oder wenn er mit VS entwickelt, er sofort auch die Code::Blocks oder KDevelop IDE in und auswendig kennt?
    usw.

    Mit einem Werkzeug sammelt man Erfahrung, welche man nicht einfach so auf ein anderes Werkzeug übertragen kann. Die Einarbeitung in das andere Werkzeug kostet wieder Zeit, Nerven und Geld. Womöglich hat man dann sogar Werkzeuge zur Hand, welche für die eigentliche Aufgabe völlig ungeeignet sind.
    Und das alles nur, weil man variadic Templates wollte 🤡

    Grüssli


  • Mod

    So, ich wollte auch mal meinen Senf dazugeben, wie man Funktionen mit beliebig vielen Parametern unbekannten Typs noch behandeln kann. Und zwar typensicher. Die Standardbibliothek macht es schließlich vor:

    #include <iostream> // Bloß zur Demonstration
    #include <string>   // Bloß zur Demonstration
    
    #include <list>
    #include <boost/any.hpp>
    
    class foo
    {
    private:
      std::list<boost::any> args;
      template<typename T> friend foo& operator<<(foo & lhs, T rhs);
    public:
      static void execute(){};
    }; 
    
    template<typename T> foo& operator<<(foo & lhs, T rhs)
    {
      lhs.args.push_back(rhs);
      return lhs;
    }
    
    template<> foo& operator<<(foo & lhs, void (*rhs)())
    {
      if (rhs==foo::execute)
        { 
          std::cout<<"Funktion aufgerufen mit " << lhs.args.size() << " Parametern.\n";
          unsigned counter=0;
          for(std::list<boost::any>::iterator i = lhs.args.begin();i!=lhs.args.end();++i )
            {
              std::cout<<++counter<<". Parameter hat typeid "<<i->type().name()<<".\n";
              // Hierhin kann Code um auf den Parametertypen zu reagieren
            }
          lhs.args.clear();
        }
      return lhs;
    }
    
    foo seppj_out;
    
    int main()
    {
      seppj_out<<1<<2<<std::string("Test")<<foo::execute;
      seppj_out<<1.<<2.<<foo::execute;
    }
    

    Man fühle sich frei, nach Belieben Templatespezialisierungen, Überladungen oder Fallunterscheidungen hinzuzufügen.

    Ausgabe bei GCC(genaue Ausgabe von typeid ist nicht standardisiert):

    Funktion aufgerufen mit 3 Parametern.
    1. Parameter hat typeid i.
    2. Parameter hat typeid i.
    3. Parameter hat typeid Ss.
    Funktion aufgerufen mit 2 Parametern.
    1. Parameter hat typeid d.
    2. Parameter hat typeid d.
    


  • Was hat boost::any mit der Standardbibliothek zu tun? Und warum machst du so ein komisches Zeugs drum rum?



  • Wenn man sich vorher auf eine Anzahl Typen festlegt, die angenommen werden können, kann man statt Boost.Any auch Boost.Variant benutzen und dann geht die Abfrage noch etwas eleganter mittels Visitors.


  • Mod

    ayayayaaa schrieb:

    Was hat boost::any mit der Standardbibliothek zu tun? Und warum machst du so ein komisches Zeugs drum rum?

    boost::any hat gar nichts damit zu tun, ich wollte bloß nicht so viel tippen für ein einfaches Beispiel. Das "komische Zeugs" ist der Kern der Idee: Erst füttert man das Funktionsobjekt mit den Parametern, dann führt man die Funktion aus.

    Da man in der Praxis wohl kaum mit beliebigen Parameterarten arbeiten wird, würde man in einer echten Umsetzung eher eine Überladung anstatt eines Templates benutzen und einen spezialisierten Container für jeden Argumententyp anstatt eines allgemeinen Containers wie boost::any.



  • Der else-Zweig in der Spezialisierung fehlt.



  • SeppJ schrieb:

    ayayayaaa schrieb:

    Was hat boost::any mit der Standardbibliothek zu tun? Und warum machst du so ein komisches Zeugs drum rum?

    boost::any hat gar nichts damit zu tun, ich wollte bloß nicht so viel tippen für ein einfaches Beispiel. Das "komische Zeugs" ist der Kern der Idee: Erst füttert man das Funktionsobjekt mit den Parametern, dann führt man die Funktion aus.

    der wollte doch nur beliebige argumente übergeben, da hätte eine std::listboost::any args gereicht.


Anmelden zum Antworten