Entwurfsmuster gesucht: Werte-Initialisierung



  • Hallo,

    ich habe öfter die Situation, dass ich eine Klasse mit vielen Werten bestücken muss. Dafür suche ich ein Codemuster.

    Um das ganze zu illustrieren, zwei Beispiele:

    * Ich habe eine 'matrix'-Klasse, welche eine Abbildung K x K -> V vornimmt, d.h. für generische K zwei Parameter auf einen Wert abbildet. Die Menge der Schlüssel wird im Konstruktor initialisiert. Da ich dem Nutzer die Wahl der Eingabe lassen wollte, habe ich das mit Iteratoren gemacht:

    matrix::matrix(FIter begin, FIter end) { std::copy(begin, end, back_inserter(m_keys)); }
    

    Das konnte man dann folgendermaßen aufrufen:

    char keys[] = { 'A', 'C', 'G', 'T' };
    matrix<char, int, 4> m(keys, keys + 4);
    

    Diese Matrix würde also Nucleinsäurebasen als Schlüssel verwenden. Das ist umständlich, aber es geht.

    * Für eine Klasse zum Abbilden von Status (eine FSM für ein hidden Markov model) benötige ich eine Menge von Ausgaben ("emission" oder "observation", Beobachtung) zusammen mit ihren relativen Wahrscheinlichkeiten. Hierfür habe ich eine "builder style" Initialiserungsliste gewählt, weil ich denke, dass das die wenigste Schreibarbeit ist. Das sieht dann z.B. so aus:

    state<int> loaded;
    double const u = 1.0 / 10.0;
    double const uu = 1.0 / 2.0;
    
    loaded.emit(1, u).emit(2, u).emit(3, u).emit(4, u).emit(5, u).emit(6, uu);
    

    Wie man leicht erraten kann, gibt 'emit' eine Referenz auf '*this' zurück.
    Hier wird ein gezinkter Würfel modelliert, der mit erhöhter Wahrscheinlichkeit eine 6 würfelt.

    Ich bin nun mit dieser Art der Initialisierung irgendwie unzufrieden. Es muss doch irgendein einheitliches Muster geben, das einen große Mengen an Daten initialisieren lässt. Könnte mir bitte jemand helfen? Ich sammle auch allgemein Vorschläge, auch wenn es sich dabei nicht um etablierte Entwurfsmuster handelt -- ich brauche einfach eine konzise Kurzschreibweise, die wiederverwendbar ist.

    Die in boost::Spirit gewählte Art der Initialisierung von Listen (also m.keys = 'A', 'C', 'G', 'T') mag ich allerdings nicht, da der Operator "," in C++ für mich anders belegt ist (außerdem ist mir das zuviel Schreibaufwand, dafür einen Handler zu implementieren).



  • du könntest eine emiterklasse schreiben, und dann folgenden code nutzen

    loaded.emitter()(1,u)(2,u)(3,u)(4,u)(5,u)(6,uu);
    


  • Hi r0nny,

    das ist eine Lösung. Allerdings hat sie ein Problem, das auch die boost-Lösung hat: Man muss einen Proxy schreiben. Na ja, schlimmstenfalls mache ich das auch noch, besser als nichts.


Log in to reply