S
Ich wuerde euch gerne eine Loesung fuer ein problem von mir darlegen.
Mich wuerde interessieren, was ihr von der loesung haltet - wo ist sie schlecht, wo ist sie ganz schlecht und wo ist sie einfach nur falsch. (;))
Problem war:
es gibt Container die werte paare speichern (name und value)
wie sie diese werte paare speichern soll egal sein (ob vector, sorted vector, map, set,...)
man kann ueber Container.get(name) an den korrespondierenden wert kommen.
doch wie kann man durch alle werte iterieren (in meinem fall will ich alle wertepaare ausgeben (zB fuer debug messages))??
man koennte natuerlich zB std::pair verlangen - aber ich will dem container alle freiheiten lassen, die er braucht.
also braucht man eine moeglichkeit aus pair<name, value> zwei strings (name, value) zu machen -> dispatcher
meine loesung sieht folgendermassen aus:
Display steht fuer mehrere klassen, die die wertepaare ausgeben (zB DisplayHTML, DisplayCSV,...)
Container ist der genannte Container typ - er speichert die wertepaare intern - wie er das macht ist fuer fremde uninteressant.
Functor - der mittelsmann. er vermittelt zwischen Container und Display. Er ruft Container::dispatch mit Display als parameter auf -> so kann Container::dispatch() Display die echten werte geben.
#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
//zeigt werte an
//steht fuer eine sammlung an 'Displayern' die die daten
//in jeweils anderen formaten anzeigen (HTML, XML, CSV,...)
struct Display
{
void print(string const& name, string const& value)
{
cout<<name<<" == "<<value<<'\n';
}
};
//ein proxy functor der zwischen Display und Container vermittelt
template<class Value, class Dispatcher>
class Functor
{
public:
typedef void (Value::*Func)(string const&, string const&);
private:
Value val;
Func func;
public:
//nimmt ein objekt + pointer auf Display::print()
Functor(Value const& t, Func f)
: val(t), func(f)
{
}
//generischer op() - damit er mit allen moeglichen
//typen laeuft - T ist hier ja uninteressant
template<typename T>
void operator()(T i)
{
Dispatcher::dispatch(i,val,func);
}
};
class Container
{
private:
struct Value
{
string name;
string value;
Value(string const& name, string const& value)
: name(name), value(value)
{
}
};
vector<Value> vec;
public:
typedef vector<Value>::const_iterator const_iterator;
void insert(string const& name, string const& value)
{
vec.push_back(Value(name,value));
}
const_iterator begin() const
{
return vec.begin();
}
const_iterator end() const
{
return vec.end();
}
//ruft obj.func() mit den dispatchten werten auf
//aus Values wird name und value
template<class Obj>
static void dispatch(Value const& val, Obj obj, void (Obj::*func)(string const&, string const&) = &Obj::operator())
{
(obj.*func)(val.name, val.value);
}
};
int main()
{
Container c;
c.insert("Name1","Value1");
c.insert("Name2","Value2");
c.insert("Name3","Value3");
Display display;
for_each(c.begin(),c.end(),Functor<Display, Container>(display,&Display::print));
}
der code sollte richtig sein, wenn euch fehler auffallen nur her damit.
aber eigentlich will ich wissen, was ihr davon haltet - ists zu umstaendlich geloest, zu schwer zu lesen, gibts eine bessere moeglichkeit, oder ist der code vielleicht sogar gut?
danke fuer euer feedback!