Probleme mit typedef std::list<boost::any> many;



  • habe aber jetzt folgenden Code zum laufen gebracht...

    #include <string>
    #include <iostream>
    #include <list>
    #include <boost/any.hpp>
    #include <stdio.h>
    
    using boost::any_cast;
    typedef std::list<boost::any> many;
    
    /*
    struct property
    {
        property();
        property(const std::string &, const boost::any &);
    
        std::string name;
        boost::any value;
    };
    
    typedef std::list<property> properties;
    */
    
    // append_xxxx
    
    void append_int(many & values, int value)
    {
        boost::any to_append = value;
        values.push_back(to_append);
    }
    
    void append_string(many & values, const std::string & value)
    {
        values.push_back(value);
    }
    
    void append_char_ptr(many & values, const char * value)
    {
        values.push_back(value);
    }
    
    void append_any(many & values, const boost::any & value)
    {
        values.push_back(value);
    }
    
    void append_nothing(many & values)
    {
        values.push_back(boost::any());
    }
    
    /// IS_xxxxx
    
    bool is_empty(const boost::any & operand)
    {
        return operand.empty();
    }
    
    bool is_int(const boost::any & operand)
    {
        return operand.type() == typeid(int);
    }
    
    bool is_char_ptr(const boost::any & operand)
    {
        try
        {
            any_cast<const char *>(operand);
            return true;
        }
        catch(const boost::bad_any_cast &)
        {
            return false;
        }
    }
    
    bool is_string(const boost::any & operand)
    {
        return any_cast<std::string>(&operand);
    }
    
    //  count_all
    
    void count_all(many & values, std::ostream & out)
    {
        out << "#empty == "
            << std::count_if(values.begin(), values.end(), is_empty) << std::endl;
        out << "#int == "
            << std::count_if(values.begin(), values.end(), is_int) << std::endl;
        out << "#const char * == "
            << std::count_if(values.begin(), values.end(), is_char_ptr) << std::endl;
        out << "#string == "
            << std::count_if(values.begin(), values.end(), is_string) << std::endl;
    }
    
    int main()
    {
    
      many values;
    
      append_int(values,3);
      append_int(values,1);
      append_int(values,4);
      append_int(values,5);
      append_int(values,6);
      append_int(values,8856);
    
      append_any(values,23223);
    
      append_string(values,"test");
      append_string(values,"asa");
      append_string(values,"tast");
      append_string(values,"sd");
      append_string(values,"ddsdt");
    
      append_any(values,"tste");  //wird irgendwie nicht mitgezählt
    
      std::cout << std::count_if(values.begin(), values.end(), is_int)<<std::endl;  // 7
      std::cout << std::count_if(values.begin(), values.end(), is_string)<<std::endl; // 5
    
     return 0;
    }
    

    wie es scheint speichert er die werte jeweils in values ab...
    mitm Zählen happert es etwas... woran kann das liegen??

    die Int Werte zählt er richtig, aber die String Werte nicht...
    registriert der die

    append_any(values,"tste");
    

    nicht als string??
    wieso macht er es dann bei der Zeile

    append_any(values,23223);
    

    ???

    nun wollte ich die gesammte Liste auf der Console ausgeben...
    nur habe ich keinen Plan wie das geht...
    hat jemand entsprechenden Code dafür??
    gibt es sowas wie count_if auch für die Ausgabe??
    wo ist dieses count_if definiert???
    in Boost??
    finde leider in der Boost Hilfe nichts zu dem count_if
    und in den man Pages auch nicht...

    wie kann ich auf einzelne Elemente zugreifen in der Liste??

    benötige ich dafür wieder einen Iterator??
    wenn ja, wie erzeuge ich den für listboost::any ??
    und wie sieht dann der code zur ausgabe der Liste aus??

    merci schon mal

    ufosworld



  • Um einen std::string in einem any zu Speichern musst du ihm auch ein std::string-Objekt übergeben und keine Zeichenkette 💡

    Und noch was:

    template< typename type >
    bool is( const boost::any& operand )
    {
      return operand.type() == typeid( type );
    }
    

    ist doch viel schöner als deine ganzen Code-Duplikate. Gleiches gilt für append.

    Edit:

    Zu deinen Fragen bezüglich std::list
    Wie wäre es wenn du dir einfach mal die Doku oder ein Tutorial über std::list bzw. die STL zu Gemüte führst 💡

    Und ein count_if tut genau das was der Name sagt. Eine bedingte Ausgabe würde wohl print_if heißen und die müsstest du selber schreiben.



  • Wie du an dem Präfix std:: erkennst, gehört count_if() nicht zu Boost, sondern zur C++ Standard-Bibliothek. Und auf die Elemente zugreifen kannst du mit einem ganz normalen Listen-Iterator for(manyiterator p=values.begin();p!=values.end;++p) mach_was(*p); (ich bin mir nicht sicher, ob du den Inhalt eines any direkt ausgeben kannst).

    PS: Zeichenketten-Literale sind in C++ keine std::string's, sondern 'const char*', also sollte der Eintrag "tste" als 'char_ptr' gezählt werden.



  • danke schon mal für die antworten... das mit count_if hab ich dann 10 minuten später selbst rausgefunden....

    und zu dem

    (ich bin mir nicht sicher, ob du den Inhalt eines any direkt ausgeben kannst).
    

    da scheinst du nicht der einzige zu sein 😉

    werde das mal a weng ausprobieren... wie ich das hinbastel das ich das rauswerfe wenn ich any datentyp ausgeben will

    merci euch beiden

    ufosworld 😉



  • also, hab das jetzt eingebaut.. ( die for-Schleife)

    und wollte den Iterator ausgeben... aber das geht nicht...

    also weder

    std::cout << *it <<std:endl;
    

    geht, noch

    std::cout << it <<std:endl;
    

    geht, noch

    std::cout << values.it <<std:endl;
    

    geht.

    bei

    std::cout << &it <<std:endl;
    

    wirft er mit 12 mal die adresse raus, in der it gespeichert ist...

    aber leider schaff ich es nicht die gespeicherten Werte auszugeben 😞 😡

    Irgendwelche Vorschläge? 😕

    grüsse UFOSWORLD



  • Versuch mal:

    std::cout << boost::any_cast<std::string>(*it) << std::endl;
    


  • Ok das geht soweit...
    nun wollte ich in der Liste gespeicherte Werte verändern/tauschen

    hab da den Befehl swap bei List gefunden

    aber wie der Code hier aussieht kann man mit dem Swap Befehl nur ganze Listen tauschen

    // swap lists
    #include <iostream>
    #include <list>
    using namespace std;
    
    main ()
    {
      list<int> first (3,100);   // three ints with a value of 100
      list<int> second (5,200);  // five ints with a value of 200
      list<int>::iterator it;
    
      first.swap(second);
    
      cout << "first contains:";
      for (it=first.begin(); it!=first.end(); it++) cout << " " << *it;
    
      cout << "\nsecond contains:";
      for (it=second.begin(); it!=second.end(); it++) cout << " " << *it;
    
      cout << endl;
    
      return 0;
    }
    

    gibt es auch eine Funktion mit der ich direkt auf die Elemente der liste zugreifen und diese verändern kann.

    Will folgendes machen können.
    - Werte tauschen innerhalb der Liste
    - Werte verändern
    - Werte in neuer Liste an andere Position schreiben

    gruss UFO



  • Wenn du zwei Iteratoren hast, kannst du mit

    std::iter_swap(it1, it2);
    

    die Inhalte vertauschen (also nicht die Iteratoren werden getauscht, sondern die Daten auf die die Iteratoren "zeigen").



  • Zum ändern kannst du ja einfach den entsprechenden Iterator verwenden.
    Einfügen geht z.Bsp. über insert.



  • Th schrieb:

    Wenn du zwei Iteratoren hast, kannst du mit

    std::iter_swap(it1, it2);
    

    die Inhalte vertauschen (also nicht die Iteratoren werden getauscht, sondern die Daten auf die die Iteratoren "zeigen").

    mhh irgendwie geht da was nicht...
    habe zwei iteratoren . einer heisst it und zeigt auf begin() und der andere heisst endit und zeigt auf end()
    erzeugt hab ich die mit folgendem befehlen:

    many::iterator it     = values.begin();  //erzeuge Iterator it und setze auf values.begin()
    many::iterator endit  = values.end();    //erzeuge Iterator endIt und setzte auf values.end()
    

    wobei beide auf die folgende Struktur verweisen...

    using boost::any_cast;
    typedef std::list<boost::any> many; 
    many values; 
    
    using namespace std;
    

    die liste wurde vorher mit werten befüllt...

    append_int(values,0);
        append_int(values,1);
        append_int(values,4);
        append_int(values,5);
        append_int(values,6);
        append_int(values,8856);
        append_any(values,12322131);
        append_string(values,"012345678901234567890123456789");
        append_string(values,"asa");
        append_string(values,"tast");
        append_string(values,"sd");
    

    so funktioniert ausgabe der Liste einwandfrei..

    kompilieren kann er es ... aber beim Ausführen kackt er ab 😮
    wenn ich programm ausführe und
    die beiden tauschen möchte dann kommt nur immer die Meldung: Abbruch

    was is da falsch dran?

    p.s. #include <algorithm> ist auch mit dabei 😉



  • end zeigt hinter das letzte Element, also auf kein Gültiges element. Wenn du das versuchst zu tauschen ist ist das nicht so toll



  • Helium schrieb:

    end zeigt hinter das letzte Element, also auf kein Gültiges element. Wenn du das versuchst zu tauschen ist ist das nicht so toll

    merci... das hab ich dann auch rausgefunden...

    hier die eine Lösung..

    vector<int>::iterator first = v.begin(), last  = v.end();
    
    --last; // auf letztes Element zeigen lassen
    
    iter_swap(first, last);         // Tausch
    

    aber schon komisch... hab rumgesurft und fast überall wo das erste mit dem letzten Element getauscht wird... steht die Lösung

    iter_swap(first, last);

    ohne das --last;

    ab und zu steht auch sowas dort:

    iter_swap(v.begin(),v.end()-1);

    nur da kackt er gleich beim kompilieren ab... das frisst mein kompiler gar nicht...



  • UFOSWORLD schrieb:

    aber schon komisch... hab rumgesurft und fast überall wo das erste mit dem letzten Element getauscht wird... steht die Lösung

    iter_swap(first, last);

    ohne das --last;

    Bei sowas mußt du vermutlich auch gucken, wie first und last definiert sind (manche Autoren definieren Bereiche mit einschließlichen Grenzen - d.h. last zeigt auf das letzte Element und nicht dahinter).

    ab und zu steht auch sowas dort:

    iter_swap(v.begin(),v.end()-1);

    nur da kackt er gleich beim kompilieren ab... das frisst mein kompiler gar nicht...

    Ja, sowas geht auch nur mit Random Acess Iteratoren - und list<> hat "nur" bidirektionale Iteratoren.



  • iter_swap benötigt Forward-Iteratoren und sollte so auch problemlos mit list gehen. Im Josuttis ist sogar ein Beispiel damit. 🙂



  • Braunstein schrieb:

    iter_swap benötigt Forward-Iteratoren und sollte so auch problemlos mit list gehen. Im Josuttis ist sogar ein Beispiel damit. 🙂

    iter_swap ja, aber was ist mit dem Ausdruck "v.end()-1"... 😉

    cu André



  • list::end() liefert einen bidirektionalen Iterator auf eine Position hinter dem letzten Element. Es sollte also gehen. Obwohl mir, ehrlich gesagt, der Ausdruck nicht gefällt.



  • Braunstein schrieb:

    list::end() liefert einen bidirektionalen Iterator auf eine Position hinter dem letzten Element.

    Und deshalb klappt der Ausdruck "end()-1" gerade nicht - eine Subraktion von Iteratoren ist nur für Random Access Iteratoren definiert, bei bidirektionalen könntest du höchstens advance() verwenden: iter_swap(v.begin(),advance(v.end(),-1));



  • Ok, das ist richtig.
    aber --v.end() sollte gehen.



  • Ok danke euch allen erst mal für die Antworten.

    Es funktioniert perfekt... aber nur wenn ich Elemente gleichen Datentyps tauschen möchte.

    Boost::Any hat ja den Vorteil das man da erstmal alles reinpacken kann...
    er identifiziert das dann entsprechend...

    jetzt wollte ich ein String Element am Anfang mit einem IntegerWert am Ende tauschen.... aber da bringt er wieder nur ABBRUCH.

    auch habe ich probiert die Werte jeweils im Datentyp Any zu speichern,
    nur er wandelt z.b.

    append_any(values,"Test"); intern in einen Char_Ptr um
    und
    append_any(values,12345); intern in einen Integer Wert um
    und
    append_string(values,"Test"); ist von der definition her schon ein String Wert.

    stösst hier iter_swap an seine Grenzen und gibt es eine Möglichkeit diese Werte trotzdem zu tauschen?

    desweiteren nervt etwas, das man nicht it = it+5; machen kann
    sondern 5 mal it++; machen muss , wenn man auf das 6te Element navigieren möchte... um dieses z.b. zu removen...

    merci schon mal



  • Wenn du sehr viel Wert darauf legst, direkt über den Index auf die Elemente zugreifen zu können, ist list<> wohl die falsche Wahl - Direktzugriff bieten (von den std-Containern) nur vector<> und deque<>.

    PS: Die einzigen Grenzen, an die iter_swap() stoßen könnte, sind singuläre Iteratoren (v.end()) oder falsche Kopier-Semantik (aber das wäre ein Problem von any).


Anmelden zum Antworten