PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : BOOST::any und die Problemchen damit



ufosworld
19-07-2007, 12:46
Nachdem ich nun Boost in mein Projekt eingebunden habe für die Übergabe der Parameter musste ich feststellen das man mit Boost ziemlich beschränkt ist....

Den Example Code von www.boost.org habe ich auch verwendet...

Problemstellung. Framework, das mir diverse .so Files lädt und auf Funktionen zugreift.

soo nun aber die entscheidenden Codesegmente:
Hinzufügen der Daten im Modul Input:




......

for (int a = 1; a<=10; a++)
{
char c[2] ;

//cout << c << endl;

char x1[50] ;

int gaga =65 + a ;

c [ 0 ] = gaga ;
c [ 1 ] = '\0' ;

x1 [ 0 ] = '\0' ;
strcat ( x1 ,"Char_prt1 " ) ;
strcat ( x1 ,c ) ;
printf ( "t1: <%s>\n" , x1 ) ;
append_any(values,x1);

x1 [ 0 ] = '\0' ;
strcat ( x1 ,"Char_ptr2 " ) ;
strcat ( x1 ,c ) ;
printf ( "t2: <%s>\n" , x1 ) ;
append_any(values,x1);
x1 [ 0 ] = '\0' ;
strcat ( x1 , "ich bin ein String-Wert " ) ;
strcat ( x1 ,c ) ;
printf ( "t3: <%s>\n" , x1 ) ;
append_string(values,x1);

// append_any(values,12.340); // Float Wert

append_any(values,12340+a);
append_any(values,11110+a);
append_int(values,22220+a);
append_int(values,54320+a);
append_nothing(values); // nichts anfügen...
}

// Werte via Variable hinzufügen
int wert;
wert = 9999999;
append_any(values,wert);

count_all(values);
print_all(values);

return values;
.....



mit diesem Codesegment füge ich Daten in den


typedef std::list<boost::any> many;
many values;
ein.

Das am Anfang mit der Laufvariable a ist nur dafür da, das er nicht überall die selben Daten reinschreibt... (hierdurch bin ich erst darauf gestossen das das schreiben auf char ptr auch nicht geht--> siehe unten)

Nun folgt der Code für die Funktionen zum hinzufügen und identifizieren der Daten, die gespeichert werden sollen. Dies sind die standardfunktionen von www.boost.org example any


void append_float(many & values, float value)
{
boost::any to_append = value;
values.push_back(value);
}


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

zum identfizieren der Daten werde Funktionen mit dem Rückgabetyp bool genutzt.



bool is_empty(const boost::any & operand)
{
return operand.empty();
}

bool is_int(const boost::any & operand)
{
return operand.type() == typeid(int);
}

bool is_float(const boost::any & operand)
{
return operand.type() == typeid(float);
}


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


in der Funktion sieht man noch die Funktionsaufrufe print_all und count_all



void count_all(many & values)
{
int zahl;
zahl=0;

std::cout << "#float == "
<< std::count_if(values.begin(), values.end(), is_float) << std::endl;
std::cout << "#int == "
<< std::count_if(values.begin(), values.end(), is_int) << std::endl;
std::cout << "#empty == "
<< std::count_if(values.begin(), values.end(), is_empty) << std::endl;
std::cout << "#string == "
<< std::count_if(values.begin(), values.end(), is_string) << std::endl;
std::cout << "#const char * == "
<< std::count_if(values.begin(), values.end(), is_char_ptr) << std::endl;

zahl = values.size();

std::cout<<"-------------------"<<std::endl;
std::cout << "Gesamt " <<zahl<<std::endl;

std::cout<<std::endl;
}



und



void print_all(many & values)
{

// für händisch test
// int intvar;

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



//*** Händisch Test kann gelöscht werden... zum test
//intvar = any_cast<int>(*it);
//std::cout << intvar<< std::endl;
//++it;
//intvar = any_cast<int>(*it);
//std::cout << intvar<< std::endl;
//++it;
//** Händisch test ende

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


// durchlaufe die gesamte Liste und gib alle Daten aus
int xxx = 0 ;
int size =0;
size = values.size();

cout << "Elemeteanzahl: "<< size << endl;

for (; it != endit; ++it)
{
// xxx++ ;

//printf ( "Outliste: %3d <%s> \n" , xxx , *it; ) ;
// std::cout << xxx << " || " << &it << " || " << &values<< std::endl;

if (is_int(*it))
std::cout << "Int: "<<any_cast<int>(*it)<<std::endl;
else if (is_float(*it))
std::cout << "Float: "<<any_cast<float>(*it)<<std::endl;
else if (is_string(*it))
std::cout << "String: "<<any_cast<std::string>(*it)<<std::endl;
else if (is_char_ptr(*it))
std::cout << "Char_Ptr: "<<any_cast<const char*>(*it)<<std::endl;
else if (is_empty(*it))
std::cout << "Empty: "<<std::endl;

}
std::cout<< std::endl;

}




nun wird bei Aufruf den Programms eine Ausgabe erzeugt die wie folgt aussieht...


IN INPUT MODUL ANGEKOMMEN!!!
t1: <Char_prt1 B>
t2: <Char_ptr2 B>
t3: <ich bin ein String-Wert B>
t1: <Char_prt1 C>
t2: <Char_ptr2 C>
t3: <ich bin ein String-Wert C>
t1: <Char_prt1 D>
t2: <Char_ptr2 D>
t3: <ich bin ein String-Wert D>
t1: <Char_prt1 E>
t2: <Char_ptr2 E>
t3: <ich bin ein String-Wert E>
t1: <Char_prt1 F>
t2: <Char_ptr2 F>
t3: <ich bin ein String-Wert F>
t1: <Char_prt1 G>
t2: <Char_ptr2 G>
t3: <ich bin ein String-Wert G>
t1: <Char_prt1 H>
t2: <Char_ptr2 H>
t3: <ich bin ein String-Wert H>
t1: <Char_prt1 I>
t2: <Char_ptr2 I>
t3: <ich bin ein String-Wert I>
t1: <Char_prt1 J>
t2: <Char_ptr2 J>
t3: <ich bin ein String-Wert J>
t1: <Char_prt1 K>
t2: <Char_ptr2 K>
t3: <ich bin ein String-Wert K>
#float == 0
#int == 41
#empty == 10
#string == 10 diese 10 String Werte passen noch
#const char * == 0 Hier fehlen 20 Werte
-------------------
Gesamt 81 die dann hier aber irgendwie dabei sind... wo sind die gespeichert??

Elemeteanzahl: 81
String: ich bin ein String-Wert B
Int: 12341
Int: 11111
Int: 22221
Int: 54321
Empty:
String: ich bin ein String-Wert C
Int: 12342
Int: 11112
Int: 22222
Int: 54322
Empty:
String: ich bin ein String-Wert D
Int: 12343

usw...

Int: 22229
Int: 54329
Empty:
String: ich bin ein String-Wert K
Int: 12350
Int: 11120
Int: 22230
Int: 54330
Empty:
Int: 9999999

Ab jetzt Work Modul
new
Name der Datei:work.so
Name der Funktion: worker

In WORK MODUL ANGEKOMMEN!!!
#float == 0
#int == 41
#empty == 10
#string == 0 Wo sind die String Werte hin?
#const char * == 0 das die weg sind wissen wir ja schon
-------------------
Gesamt 81 hier wieder gesamtzahl 81... ??? also 41+10+10 String + 20 Char Ptr

Elemeteanzahl: 81
Int: 12341
Int: 11111
Int: 22221
Int: 54321
Empty:
Int: 12342
Int: 11112
Int: 22222
Int: 54322
.... jetzt zeigt er mir auch den String nicht mehr an....

es fällt dabei folgendes auf...
1. die String Werte werden zwar gespeichert, aber sind dann nicht mehr im nächsten Modul verfügbar
2. die Char_ptr Werte müssten 20 Stück sein.... diese werden zwar bei gesamtsumme mitgezählt, aber dann nicht als solche erkannt (#const char * == 0)
3. wenn ich das // append_any(values,12.340); // Float Wert im Modul aktiv mache, so werden die Float Werte ebenfalls nicht erkannt... obwohl ich hierfür Funktion is_float geschrieben habe.

4. Allgemeine Fragen:
a. wie kann man auf Inhalt von *it zugreifen bzw auf das, worauf er zeigt?
ohne hierbei mit is_xxx rumtun zu müssen...
cout << *it << endl; geht leider nicht
ich will schlichtweg ausgeben welche Werte bei durchgang durch die Liste in selbiger gespeichert sind... also auf die nakkich gespeicherten Daten in Speicherzellen von values zugreifen....

b. Welche Datentypen kann das boost::any noch verarbeiten??
gibt es irgendwo eine Liste incl der Funktionen die dazu genutzt werden können, die entsprechenden Daten richtig reinzuschreiben und wieder herauslesen zu können??? Es kann ja wohl nicht sein, das Boost:any nur für "4" Datentypen funktioniert... int, string, char ptr und empty... wobei ja nur int nutzbar ist... da der rest nicht richtig gespeichert wird....

5. was würdet ihr Vorschlagen als Alternative zu verwenden, sollte ich das mit der Übergabe und dem speichern nicht auf die Reihe bekommen....
ALTERNATIVE zu BOOST praktisch...

anda_skoa
19-07-2007, 15:25
Kannst du versuchen, statt append_any die jeweilige Spezialform zu benutzen?

Eventuell gibt es in einer anderen Bibliothek einen einfacheren Variant Typ. Oft sind Varianttypen halt nicht so flexibel, d.h. eventuell nur auf ein paar Inhaltstypen beschränkt, dafür ohne Templates.

Ciao,
_

locus vivendi
19-07-2007, 21:43
Hallo Ufosworld,

"12.34" in C++ ist nicht vom Typ float, konsequenterweise liefert deine "is_float" Funktion für boost::any(12.34) auch false zurück.

Außerdem ist typeid(char const*) != typeid(char[50]). Es gilt, das
typeid(char*), typeid(char const*), typeid(char[10]), typeid(char[50]), allesamt unterschiedlich sind. Das ist für dich vielleicht auch relevant.

Dann wundert mich das
"char x[50]; boost::any y(x);" bei dir offenbar kompiliert. Ein Array ist nämlich nicht kopierbar und erfüllt damit nicht die Vorausetzungen um mit boost::any verwendet zu werden. Mein Compiler weist solche Versuche auch zurück. Vielleicht ist dein Compiler ja kaputt und akzeptiert soetwas ohne zu meckern.


b. Welche Datentypen kann das boost::any noch verarbeiten??
Value Types. Welche das sind ist in der Doku definiert.

ufosworld
19-07-2007, 23:07
also ich werde das Montag mal checken...

werde aber Rechner wechseln...

Gcc is der 3.2 er

Suse Linux 8.1

ufosworld
23-07-2007, 08:29
was ist 12.34 den dann?? double???

NACHTRAG: ja es ist Double jetzt speichert er die Double Werte ab und sendet diese auch mit an das nächste Modul

das mit dem char x[50] scheint er wirklich am neuen rechner (Suse 10.0 und GCC 4.0.2) nicht zu mögen... beim compilieren des Moduls meckert er

wie könnte ich das einfacher realisieren?? also das Anhängen von einem unterschiedlichen Char Wert ( 65 + 1,2,3,4 usw) also A B C D E
an eine Zeichenkette...

in der Docu finde ich irgendwie nix... vielleicht bin ich auch einfach nur blind...
es steht zwar einiges zu vales types drin, aber nicht im speziellen welche Datentypen ich in any reinpacken kann... bzw wie dann wiederrum die Ausleseroutinen sind...

also alla


void append_int(many & values, int value)
{
boost::any to_append = value;
values.push_back(to_append);
}


bool is_int(const boost::any & operand)
{
return operand.type() == typeid(int);
}