Factory für Template-Objekte



  • Hallo,

    Ich hab ne Klasse:

    template<typename TVoxel>
    class Image3d
    {
      public:
        // create empty image
        Image3d(int nWidth, int nHeight, int nDepth);
    
        // load image from disk
        Image3d(std::string& sFilePath);
    
        // return voxel at position
        TVoxel& Voxel(int nX, int nY, int nZ);
    
      private:
        std::vector<TVoxel> m_aData;  
    
        [...]
    };
    
    typedef Image3d<__uint8_t> TImageGrey8;
    typedef Image3d<__uint16_t> TImageGrey16;
    

    Nun, das funktioniert zwar iss aber etwas unflexibel da ich, bevor ich das Bild mit dem 2. Konstruktor von Platte laden will, wissen muss welchen Voxeltyp es hat.
    Da der Voxeltyp aber in den Metadaten des Bildes Codiert ist, ließe sich das auch eleganter (automatisch machen). Ich hab da an eine Factory gedacht, die das entsprechende Bild erzeugt, nachdem sie den Pixeltyp bestimmt hat.

    Mir ist aber nicht klar wie ich diese Implementieren soll, ich kann ja keinen Basisklassenpointer liefern da Image3d keine Basisklasse hat, wenn ich ein
    IImage3d interface implementiere, muss ich in der pur-virtuellen Methode Voxel(int,int,int) den Rückgabewert wissen.

    Fällt jemand eine elegante Möglichkeit ein das zu implementieren?



  • Hallo,

    die Loki - Library bietet hierfür eine sehr gute Factory Klasse an.

    Der Grundgedanke ist, den einzelnen Klassen eine Nummer zuzuweisen und diese mit einem Funktor auf die Erzeugermethode in einer std::map abzulegen.

    MfG

    GPC



  • GPC schrieb:

    Hallo,

    die Loki - Library bietet hierfür eine sehr gute Factory Klasse an.

    Der Grundgedanke ist, den einzelnen Klassen eine Nummer zuzuweisen und diese mit einem Funktor auf die Erzeugermethode in einer std::map abzulegen.

    MfG

    GPC

    Ja, an Loki hatte ich auch schon gedacht, das Problem ist aber, dass ich nicht entscheiden will welcher Konstruktor aufgerufen werden soll, sondern die erzeugten Objekte unterschiedlich, bezüglich ihres Template-Parameters sind.
    So kann ich keine polymorphen Pointer zurückliefern.

    Ich hab mir mal den (nicht gerade trivialen) Beispielcode angesehen und bin auf keine Möglichkeit gekommen mein Problem damit zu lösen. Gib mir mal 'nen Tip.



  • Ach so, ich denke, ich verstehe. Du hast Image – Objekte und diese haben verschiedene Template – Parameter, korrekt?

    Aufgrund dieser willst du sie dann beim Einlesen unterscheiden? Ok, folgendes:

    Du erstellst eine Objektfabrik (oder einzelne Factory-Methoden) für alle Kombinationen von Image<T>. Dann nimmst du eine std::map und fügst jeweils eine eindeutige Zahl zusammen mit einem Zeiger auf ein Factory-Methode ein, also die Zahl 0 weist auf ein Image<A> hin, 1 wird zu Image<B> gemappt usw.

    Beim Schreiben deiner Images auf die Platte musst du diesen Wert natürlich auch abspeichern (am Besten du erstellst ein const int ID = 0; usw. Member für jeden Template-Parameter von Image, dann brauchst du dich nicht so verkopfen).

    Und beim Einlesen gleichst du die Zahl einfach mit der std::map ab um zu sehen, welches Image<T> geladen wird. Okay?

    MfG

    GPC



  • Templates gibts halt nur zur Compiletime danach hast du nur noch Klassen und die haben ohne Vererbung keine Beziehung zueinander, folglich kannst du die auch nicht gleich behandeln.

    Mein Vorschlag: Gib den Image-Klassen eine gemeinsame Basisklasse Image, wenn das nicht geht, dann kannst du die beiden Klassen nicht gleich behandeln und musst zwischen ihnen unterscheiden, so wie du auch zwischen einer std::map und std::ofstream unterscheiden musst.


Anmelden zum Antworten