Speicher für verschiedenartige Methodenpointer
-
hallo leute,
ein problem habe ich noch. und zwar soll die klasse daten nicht die ausgabe funktion enthalten (siehe quelltext von ssm). die ausgabe soll ebenfalls von MyDatenVector übernommen werden. mein gedanklicher hintergrund ist folgender, ich weiß nicht ob die datenspeicherobjekte "Daten" letztenendlich auf der console, einer windowsanwendung oder einem webinterface ausgegeben werden. deshalb verbietet es sich für mich die ausgabe dort zu realisieren.
ich habe mir überlegt ob es vielleicht mit rtti funktionieren könnte. und zwar könnte man doch der register-funktion den zubehandelnde datentype mitgeben.
template <class ObjectType> class MyDatenVector { // ... std::vector<ObjectType> daten; std::map<string, variant_func> funcs; // die funktionspointer std::map<string, const type_info* > types; // die funktionsrückgabetypen std::vector<string> funs; // die funktionsnamen // ... void registerFctPtr(const string &name, variant_func func, const type_info *type) { cout << "reg t: " << type->name() << endl; funcs[name] = func; types[name] = type; funs.push_back(name); } // ... } // ... int main() { MyDatenVector<Daten> myVec; // ... myVec.registerFctPtr("setName", &Daten::setName, &typeid(&Daten::setName)); myVec.registerFctPtr("getName", &Daten::getName, &typeid(&Daten::getName)); myVec.registerFctPtr("setAlter", &Daten::setAlter, &typeid(&Daten::setAlter)); myVec.registerFctPtr("getAlter", &Daten::getAlter, &typeid(&Daten::getAlter)); // ...bei der ausgabe müsste man nun die funktionen welche ja erstmal vom typ variant_func sind in den richtigen typ umwandeln. nur wie?
template <class ObjectType> class MyDatenVector { // ... void printDaten() { for(unsigned int i = 0; i!= daten.size(); i++) { for(unsigned int j = 0; j!= funs.size(); j++) { if(funs[j].substr(0, 3) == string("get")) { cout << "funcs: " << funs[j] << endl; variant_func func = funcs[funs[j]]; typedef void (ObjectType::*FGetSign)(); types[funs[j]] originFunc = boost::get<types[funs[j]]>(func); // hier irgendwie umwandeln cout << boost::bind(originFunc, &daten[i], _1)(); } } } } // ... } // ...also wenn ich die umwandlung hinbekommen würde wäre mein problem gelößt. für ideen, vorschläge oder anregungen wäre ich sehr dankbar.
eine gute nacht wünscht,
sjoe
-
Hallo js,
ist auch ganz einfach. So sieht das aus:
Output:
Object 008A3D48 Method name = getAlter, result = 30 Method name = getName, result = AAA Object 008A3D68 Method name = getAlter, result = 25 Method name = getName, result = SSS Object 008A3D88 Method name = getAlter, result = 20 Method name = getName, result = FFFSource Code
//BOOST #include <boost/bind.hpp> #include <boost/variant.hpp> //STL #include <vector> #include <map> #include <string> #include <iostream> using namespace std; class Daten { private: string Name; int Alter; public: Daten(string n, int a) : Name(n), Alter(a) { } void setName(string n) { Name = n; } string getName() const { return Name; } void setAlter(int a) { Alter = a; } int getAlter() const { return Alter; } }; class output_to_stream : public boost::static_visitor<std::ostream &> { public: output_to_stream(std::ostream &os, const Daten &daten) : os(os), daten(daten) { } template<typename T> std::ostream & operator()(T obj) const { assert(0 && "is not getter!!!"); return os; } template<typename T> std::ostream & operator()(T (Daten::*func)() const) const { return os << (daten.*func)(); } private: std::ostream &os; const Daten &daten; }; class MyDatenVector { typedef void (Daten::*FSetString)(string); typedef string (Daten::*FGetString) () const; typedef void (Daten::*FSetInt)(int); typedef int (Daten::*FGetInt)() const; typedef boost::variant<FGetString, FGetInt, FSetInt, FSetString> variant_func; std::vector<Daten> daten; std::map<string, variant_func> funcs; public: void push_back(const Daten &obj) { daten.push_back(obj); } void registerFctPtr(const string &name, variant_func func) { funcs[name] = func; } void printDaten() const { typedef std::vector<Daten>::const_iterator daten_citer; typedef std::map<string, variant_func>::const_iterator funcs_citer; daten_citer dit = daten.begin(), dend = daten.end(); while(dit != dend) { const Daten &obj = *dit; std::cout << "Object " << &obj << "\n"; funcs_citer fit = funcs.begin(), fend = funcs.end(); while(fit != fend) { const std::string &funcName = fit->first; if(funcName.substr(0, 3) == "get") { std::cout << "\tMethod name = " << funcName << ", "; std::cout << "result = "; boost::apply_visitor(output_to_stream(std::cout, obj))(fit->second); std::cout << std::endl; } ++fit; } ++dit; } } }; int main() { MyDatenVector myVec; myVec.push_back(Daten("AAA", 30)); myVec.push_back(Daten("SSS", 25)); myVec.push_back(Daten("FFF", 20)); myVec.registerFctPtr("setName", &Daten::setName); myVec.registerFctPtr("getName", &Daten::getName); myVec.registerFctPtr("setAlter", &Daten::setAlter); myVec.registerFctPtr("getAlter", &Daten::getAlter); myVec.printDaten(); }MfG.
ssm
-
fantastisch, die ausgabe funktioniert prima.
ich habe jetzt mal versucht das ganze auf eine eingabe zu adaptieren, leider funktioniert das ganze nicht so wie ich will.
template <class ObjectType> class stream_to_methode : public boost::static_visitor<> { private: std::istream &is; const ObjectType &in_obj; public: stream_to_methode(std::istream &is, const ObjectType &in_obj) : is(is), in_obj(in_obj) { } template <typename T> void operator()(void (ObjectType::*func)(T)) const { T t; is >> t; (in_obj.*func)(t); } };und der aufruf
template <class ObjectType> class MyDatenVector { //... void readDaten() const { typedef std::vector<ObjectType>::const_iterator daten_citer; typedef std::map<string, variant_func>::const_iterator funcs_citer; daten_citer dit = daten.begin(), dend = daten.end(); while(dit != dend) { const ObjectType &obj = *dit; std::cout << "Object " << &obj << "\n"; funcs_citer fit = funcs.begin(), fend = funcs.end(); while(fit != fend) { const std::string &funcName = fit->first; if(funcName.substr(0, 3) == "set") { std::cout << "\tMethod name = " << funcName << ", "; std::cout << "input: "; boost::apply_visitor(stream_to_methode<ObjectType>(std::cin, obj), fit->second); } ++fit; } ++dit; } } };vielleicht kannst du mir dazu nochmal einen tipp geben.
vielen dank schon mal im voraus,
sjoe
-
du hast fast alles richtig gemacht, weiter so!
so würde ich es machen:template <class ObjectType> class stream_to_methode : public boost::static_visitor<> { private: std::istream &is; /*!!!const*/ ObjectType &in_obj; public: stream_to_methode(std::istream &is, /*!!!const */ ObjectType &in_obj) : is(is), in_obj(in_obj) { } /*!!!*/ template<typename T> void operator()(T obj) const { assert(0 && "is not setter!!!"); } template <typename T> void operator()(void (ObjectType::*func)(T))/*!!!const */ { T t; is >> t; (in_obj.*func)(t); } };der aufruf:
void readDaten()/* !!! const */ { /*!!!*/ //typedef std::vector<ObjectType>::const_iterator daten_citer; typedef std::vector<ObjectType>::iterator daten_iter; typedef std::map<string, variant_func>::const_iterator funcs_citer; daten_iter dit = daten.begin(), dend = daten.end(); while(dit != dend) { /*!!!const */ObjectType &obj = *dit; std::cout << "Object " << &obj << "\n"; funcs_citer fit = funcs.begin(), fend = funcs.end(); while(fit != fend) { const std::string &funcName = fit->first; if(funcName.substr(0, 3) == "set") { std::cout << "\tMethod name = " << funcName << ", "; std::cout << "input: "; //!!! boost::apply_visitor(stream_to_methode<ObjectType>( std::cin, obj))(fit->second); } ++fit; } ++dit; } }Die Fehler hab ich mit "!!!" markiert.
-
hey,
was heisst da explicit? was macht das genau?
struct Print { public: explicit Print(std::ostream &os) : os(os) { }cu
-
hallo ssm,
also dein code funktioniert eigentlich gut. unter ms visual studio 2005 express, leider benutze ich aber eclipse mit cdt und mingw, also gnu.
dort will folgendes einfach nicht durch den compilerboost::apply_visitor(stream_to_methode<ObjectType>(std::cin, obj))(fit->second); // ... boost::apply_visitor(output_to_stream(std::cout, obj))(fit->second);ich habe es mal mit der ersatz konstruktion probiert
boost::apply_visitor(stream_to_methode<ObjectType>(std::cin, obj), fit->second); // ... boost::apply_visitor(output_to_stream(std::cout, obj), fit->second);für output_to_stream funktioniert es, aber für stream_to_methode leider nicht (0 && "is not setter!!!").
gibt es dafür ein workaround?
mfg sjoe
-
-mingw Version?
-BOOST Version
-Fehlermeldung?
-
serbi schrieb:
was heisst da explicit? was macht das genau?
-
-mingw Version?
-BOOST Version
-Fehlermeldung?schuldigung.
for(map<string, variant_func>::iterator iter = getter.begin(); iter != getter.end(); iter++) { cout << iter->first << ": "; boost::apply_visitor(output_to_stream<ObjectType>(cout, DV.at(pos)))(iter->second); // hm cout << endl; }die dritte zeile wird angemeckert. und zwar mit folgendem:
../DataVectorCmd.h:97: could not convert `output_to_stream<Daten>((&std::cout), (+(this + 24)->std::vector<_Tp, _Alloc>::at(unsigned int) [with _Tp = Daten, _Alloc = std::allocator<Daten>](pos)))' to `output_to_stream<Daten>&' C:/Boost/include/boost-1_33_1/boost/variant/detail/apply_visitor_delayed.hpp:79: in passing argument 1 of `boost::apply_visitor_delayed_t<Visitor> boost::apply_visitor(Visitor&) [with Visitor = output_to_stream<Daten>]'mingw version 3.2.3
boost version 1.33.1mfg sjoe
-
versuch mal so:
const ObjectType &myObj = DV.at(pos); output_to_stream<ObjectType> myVisitor(std::cout, myObj); variant_func myFunc = iter->second; boost::apply_visitor(myVisitor, myFunc);
-
spuer, funktioniert.
vielen dank,
sjoe
-
When a constructor is specified as explicit, no automatic conversion will be used with that constructor --it will only be used when an initialization exactly matches a call to that constructor.
was heisst das zu deutsch?
-
serbit schrieb:
was heisst das zu deutsch?
siehst du jetzt den Unterschied ?
class A { public: explicit A(const char *) { } }; class B { public: B(const char *) { } }; void foo1(const A &a) { } void foo2(const B &b) { } int main() { //------------------------------------------------------------------------- //error C2440: 'initializing' : cannot convert from 'const char [2]' to 'A' //A a = "!"; //OK! B b = "!"; //------------------------------------------------------------------------- //------------------------------------------------------------------------- //OK! A a1("!"); //OK! B b1("!"); //------------------------------------------------------------------------- //------------------------------------------------------------------------- //error C2664: 'foo1' : cannot convert parameter 1 from 'const char [2]' to 'const A &' //foo1("!"); //OK! foo2("!"); //------------------------------------------------------------------------- }