PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : typedef std::list<boost::any> many; - Beispiel



ufosworld
14-06-2007, 13:38
Folgende Frage.

habe von der Boost.org Seite das Beispiel


#include <list>
#include <boost/any.hpp>

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

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());
}

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);
}

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;
}


kopiert...
nachdem ich oben noch zwei Zusätzliche Includes gemacht habe kompiliert er es jetzt auch...

nun die Frage...
ich wollte nun mit der Funktion


append_any(many & values, const boost::any & value)

einen beliebigen Wert hinzufügen...

nur hab ich keinen plan wie der Aufruf der Funktion sein soll

desweiteren

wo ist dieser

values -Wert zu finden??
wird dieser nur durch den Aufruf der Funktion erzeugt??

kann mir jemand einen Beispielaufruf einer Funktion zeigen, mit dem ein Wert zugewiesen wird?

merci UFOSWORLD

p.s. für was brauche ich diesen Code

struct property
{
property();
property(const std::string &, const boost::any &);

std::string name;
boost::any value;
};

typedef std::list<property> properties;



class consumer
{
public:
virtual void notify(const any &) = 0;
...
};

ufosworld
15-06-2007, 12:13
folgenden Code wollte ich testhalber mal Boost::any tauglich machen... klappt aber nicht..




#include <string>
#include <iostream>
#include <list>
#include <boost/any.hpp>
#include <stdio.h>

typedef std::list<int> Listera; //creating a list
//typedef std::list<boost::any> intList; //creating a list

int main()
{


Listera intList;

for(int i=1; i<=6; i++) intList.push_back(i);


std::list<int>::iterator it; //modyfing list
//std::list<boost::any>::iterator it; //modyfing list

for(it = intList.begin(); it != intList.end(); it++)
{
if(*it == 3) //deleting an element in the middle
{
intList.erase(it);
it--;
}


}

//showing list
for(it = intList.begin(); it != intList.end(); it++)
printf("value = %d\n", *it);
//Ausgabe für boost::any = ???


return 0;
}

hat jemand hilfreiche Tips wie ich den Code so umschreibe, das er statt int Variablen, jeden Wert speichern und ausgeben kann?
also nicht nur die Zahlen 1-6 sondern z.b. auch Texte

anda_skoa
15-06-2007, 16:55
Dem Boost Beispiel zu Folge braucht man für "int" einen Zwischenschritt.

Probier statt direktem push_back die Funktion append_int() aus dem Beispiel, also


for(int i=1; i<=6; i++) append_int(intList, i);


Ciao,
_

ufosworld
21-06-2007, 15:11
ok irgendwie hat das nicht geklappt... 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 list<boost::any> ??
und wie sieht dann der code zur ausgabe der Liste aus??


merci schon mal

ufosworld

anda_skoa
21-06-2007, 15:49
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...

Doch, tut er. Du hast 5 Stringwerte, 7 Intwerte und einen Charpointerwert.



registriert der die

append_any(values,"tste"); nicht als string??

Nein, "tste" ist ein "const char*", kein std::string



wieso macht er es dann bei der Zeile


append_any(values,23223);

???

Es gibt eine implizite Konversion von int nach any.
Das trifft auch für den "const char*" zu, daher muss der Compiler den "const char*" nicht erst in einen std::string umwandeln, bevor er das any Object erzeugt.

Das hier sollte dein gewünschtes Ergebnis erzielen:

append_any(values,string("tste"));



gibt es sowas wie count_if auch für die Ausgabe??

Es gibt einen Standard "Copy" Algorithmus, der auf Iteratoren angewendet werden kann und einen Möglichkeit, einen Zielinterator auf einem Outputstream zu erzeugen (allerdings weiß ich das nicht auswendig)



wo ist dieses count_if definiert???
in Boost??

Nein, das gehört zur C++ Standard Template Library STL, Header <algorithm> wenn ich nicht irre.



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

benötige ich dafür wieder einen Iterator??

Iterator oder Indexoperator des Containers.
Im Falle einer Liste ist der Iterator performanter



wenn ja, wie erzeuge ich den für list<boost::any> ??


In C++ geht das ziemlich generell so:


IteratorTyp variable = container.begin();

also in deinem Fall zB


std::list<boost::any>::iterator it = values.begin();

bzw. da du ein typedef hast


many::iterator it = values.begin();


Eine Schleife mit einem Iterator kann man so machen


many::iterator it = values.begin();
many::iterator endIt = values.end();
for (; it != endIt; ++it)
{
}

Bzw., falls man nichts ändern möchte, oder nicht kann, weil der Container eine const Reference ist


many::const_iterator it = values.begin();
many::const_iterator endIt = values.end();
for (; it != endIt; ++it)
{
}


Ciao,
_

ufosworld
22-06-2007, 08:24
many::iterator it = values.begin();
many::iterator endIt = values.end();
for (; it != endIt; ++it)
{
}


ahja... und was müsste ich in die klammern schreiben??

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

???

ufosworld
22-06-2007, 09:34
also



std::cout << (*it) <<endl; ist es nicht (Tausende von Fehlermeldungen)


std::cout << (it) <<endl; ist es auch nicht


std::cout << values.it) <<endl; auch nicht

bei

std::cout << (&it) <<endl; haut er mir 13 mal die Adresse raus, in der it gespeichert ist...

wie schaffe ich es es die gespeicherten Werte auszugeben?? :( :mad:

merci UFO

anda_skoa
23-06-2007, 15:54
*it

dereferenziert erstmal nur den Iterator, d.h. du hast dann dort eine Instanz von any

An den Inhalt eine Any kommt man mit any_cast
Beispiel:


if (is_int(*it))
cout << any_cast<int>(*it);
else if (is_string(*it))
cout << any_cast<string>(*it);
else if (is_char_ptr(*it))
cout << any_cast<const char*>(*it);


Ciao,
_

ufosworld
26-06-2007, 10:01
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

ufosworld
27-06-2007, 10:05
ok habs mittlerweile rausgefunden

mit iter_swap kann man Elemente tauschen

nur hab ich nun folgendes Problem:

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? Anscheinend kann iter_swap nur Werte gleichen Datentyps 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

anda_skoa
27-06-2007, 14:57
Ansich sollte im allgemeinen Fall immer das hier funktionieren



boost::any value = *it1;
*it1 = *it2;
*it2 = value;


bzw mit std::swap

Aber wenn es einen Iterator Swap gibt (war mir bisher gar nicht bekannt), dann sollte der schon auch gehen, der Typ des Containers ist ja immer boost::any

Einen Wert ändern geht ungefähr so



boost::any newvalue = string("Foo");
many::iterator it = values.begin();
*it = newvalue;

Bzw mit Methoden der Containerklasse.

Zum Teilproblem it + 5:


it += 5;

sollte gehen.

Ciao,
_

ufosworld
28-06-2007, 07:34
also mit dem std::swap befehl,
kann man nur immer alle Werte von zwei Objekten tauschen...
siehe hier:
http://www.cplusplus.com/reference/algorithm/swap.html

das iter_swap ist kein Iterator Namens Swap sondern
eine Funktion die so heisst..
siehe hier:
http://www.cplusplus.com/reference/algorithm/iter_swap.html

Sie tauscht Werte auf die jeweils der Iterator zeigt... das geht auch innerhalb eines Objektes...


Die Funktion append_any ist bei mit so:


void append_any(many & values, const boost::any & value)
{
values.push_back(value);
}

Aber irgendwie wandelt der das dann intern ( wie mir schein in dem Boost Zeugs auf Integer oder Char_Ptr... je nachdem ob Zeichenkette oder Zahlen als Value angegeben wurden....
jedenfalls bringt er bei dem Befehl count_if
wenn ich einmal append_any mit "Testtext" und einmal mit 12345 mache
Integer = 1
Char_Ptr = 1
String = 0
Nothing = 0

(als beispiel diese Funktion... die nicht ganz läuft... aber das wichtigste is drin..


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;
}




das andere werde ich mal testen... mit dem +5
Nachtrag: mhhh das geht auch nicht...

hier mein Code + Fehlermeldung:


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

// Fehlermeldung:
// input.cpp:72: no match for `std::_List_iterator<boost::any, boost::any&,
// boost::any*>& += int' operator

Zeile 72: it +=2;
values.erase(it); //löscht den Wert "wird gelöscht" (das 3te Element)

vielleicht ist es jetzt klarer...