Wie das Beispiel aufzeigt, werden die String / CHar_Ptr Werte nur hinzugefügt, wenn ich die append_string bzw append__char_ptr Funktionen benutze
Hier liegt ein Missverständnis bei dir vor. Ein String wie "haha32" hat *nicht* den Type char* oder char const*, sondern es ist ein Array. Und wie in deinem letzten Thread um Boost.Any bereits geschrieben, kannst du Arrays nicht mit Boost.Any speichern. Du könntest also z.B. append_any(values, static_cast<char const*>("haha32") aufrufen. Und dann würde der Zeiger auch gespeichert werden. Oder du könntest append_any überladen: "void append_any(many& values, char const* str);" Diese Signatur ist beim wählen des aufzurufenden Overloads ein bevorzugter Treffer im Vergleich mit boost::any, deshalb könntest du damit auf den Cast beim Aufruf verzichten. Beide Wege habe ich dir mal gezeigt, in dem Code unten.
Dann möchte ich auch noch mal zu bedenken geben, das beim Speichern von Zeigern auf Chars immer das Problem da ist, zu entscheiden, ob der Zeiger einen String bezeichnen soll. Sprich: Wissen alle Teile die mit den Any-Werten umgehen ob ein char const* als String oder als Zeiger auf ein *einzelnes* Zeichen zu verstehen ist?
Wenn dies immer geklärt ist, spricht nichts dagegen Zeiger zu speichern. Wenn dies nicht immer klar ist, dann würde ich dazu raten nur std::strings oder Ähnliches zu speichern, und keine char const*.
Ausserdem unterschlägt er das 'a'. Wo is das?
Es ist in der Liste. Du testest nur nicht ob darin char-Werte enthalten sind. Test + Ausgabe dafür habe ich im Code unten eingebaut.
Wie ist die append_any Funktion abzuändern, sodass ich auch String /Chars Char_Ptr Werte hinzufügen kann, ohne vorab zu wissen um welchen Datentyp es sich bei dem Wert handelt... den dies ist ja dann bei append_string schon vorausgesetzt zu wissen das es ein String ist...
Ich glaube, hier verwechselst du auch etwas. Beim erstmaligen Speichern eines Wertes in ein Boost.Any hinein, ist die Forderung, dies sollte auch ohne Kenntnis des Typs gehen sinnlos. Denn an dieser Stelle ist ja garantiert das du den Typ kennst (ohne diese Information könnte der Boost.Any Konstruktor gar nicht aufgerufen werden).
Hier nun der Code. Es ist dein Beispiel von mir etwas abgeändert.
Code:
#include <iostream>
#include <stdio.h>
#include <list>
#include <boost/any.hpp>
using boost::any_cast;
typedef std::list<boost::any> many;
many values;
using namespace std;
void append_char_ptr(many & values, const char * value)
{
values.push_back(value);
}
void append_string(many & values, const std::string & value)
{
values.push_back(value);
}
void append_any(many & values, const boost::any & value)
{
values.push_back(value);
}
void append_any(many& values, char const* str)
{
values.push_back(str);
}
bool is_empty(const boost::any & operand)
{
return operand.empty();
}
bool is_int(const boost::any & operand)
{
return operand.type() == typeid(int);
}
bool is_double(const boost::any & operand)
{
return operand.type() == typeid(double);
}
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);
}
bool is_char(boost::any const& operand)
{
return operand.type() == typeid(char);
}
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 << "#double == "
<< std::count_if(values.begin(), values.end(), is_double) << 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;
out << "#char == " << std::count_if(values.begin(), values.end(), is_char) << '\n';
}
void print_all(many & values)
{
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()
// durchlaufe die gesamte Liste und gib alle Daten aus
for (; it != endit; ++it)
{
if (is_int(*it))
std::cout << "Int: "<<any_cast<int>(*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;
else if (is_double(*it))
std::cout << "Double: " <<any_cast<double>(*it) <<std::endl;
else if(is_char(*it) )
{
std::cout << "Char: " << any_cast<char>(*it) << '\n';
}
}
std::cout<< std::endl;
}
int main()
{
append_any(values,7);
append_any(values,4.3);
append_any(values,'a');
append_string(values,"test");
append_char_ptr(values,"haha32");
append_any(values, static_cast<char const*>("test32") );
append_any(values, "xyz"); // Overload von append_any beachten
std::cout << "\nAnzahl von Elementen insgesamt: " << values.size() << '\n';
count_all(values, cout);
std::cout << std::endl;
print_all(values);
return 0;
}
Lesezeichen