unique_ptr aus map auslesen und wo ist make_unique?



  • Das ist jetzt eher eine theoretische Spielerei, aber es würde mich dennoch interessieren. Ich schreibe die Frage in dieses Thema, weil sie eine Ergänzung zur vorherigen Diskussion ist.

    // --- diese Lösung funktioniert
    
        Catalog catalog{new Converter}; // Der Catalog bekommt einen Converter für die Umwandlung der Rückgabewerte mit
    
        catalog.add(new Item{"Foo"}); // neues Item : public Object => Catalog kann nur Object* speichern!
        catalog.add(new Location{"Bar"}); // neue Location : public Object
    
        catalog.find(1).asItem(); // .find liefert den Converter zurück und dieser enthält die Funktion .asItem()
        catalog.find(2).asLocation(); // dito nur diesmal ist es die Funktion .asLocation()
    
        // werden neue Typen benötigt, dann muss nur der Converter angepasst werden
    
        // --- Ist das irgendwie umsetzbar???
    
        Catalog catalog{};
    
        catalob.AddConverter{new ItemConverter}; // dieser Katalog kann nur "Items" zurückgeben
    
        catalog.addObject(new Item{"Foo"});
    
        catalog.find(1).asItem();
    
        catalog.addConverter{new LocationConverter}; // jetzt kann er "Items" und "Locations" zurückgeben
    
        catalog.addObject(new Location{"Bar"});
    
        catalog.find(1).asLocation(); // nullptr muss vom Aufrufer behandelt werden!
        catalog.find(2).asLocation();
    
        // zur Erweiterung des Katalogs müsste ein zusätzlicher Konverter hinzugefügt werden
    

    Ich habe mich bereits nach möglichen Lösungen umgeschaut, aber bisher noch nichts Brauchbares gefunden. Die Konverter müssten in einer Liste gespeichert werden, durch die iteriert und der passende Konverter aufgerufen wird. Knackpunkt ist der Rückgabewert von .find(), denn der würde dann dem jeweils gefundenen Konverter entsprechen müssen.

    Gruß,
    temi



  • Ich habe jetzt "meine" Lösung gefunden und glaube dass sie ganz gut gelungen ist.

    class Catalog
    {
        public:
            Catalog() {};
            void add(Object* object);
            template<class T> bool exists(ulong id);
            template<class T> T* get(ulong id);
        private:
            std::unordered_map<ulong, std::unique_ptr<Object>> map;
    };
    
    template<class T> bool Catalog::exists(ulong id)
    {
        static_assert(std::is_base_of<Object, T>::value, "Catalog.exists<T>(id): T is not derived from Object");
    
        return get<T>(id) != nullptr;
    }
    
    template<class T> T* Catalog::get(ulong id)
    {
        static_assert(std::is_base_of<Object, T>::value, "Catalog.get<T>(id): T is not derived from Object");
    
        return dynamic_cast<T*>(map[id].get());
    }
    

    Damit kann ich beliebige von "Object" abgeleitete Objekte speichern und erhalte den korrekten Typen über ein klares Interface wieder zurück.

    int main(int argc, char *argv[])
    {
        Catalog catalog;
    
        catalog.add(new Item{"Axt"});
        catalog.add(new Item{"Baum"});
        catalog.add(new Location{"Wald"});
    
        if (catalog.exists<Item>(42))
            cout << catalog.get<Item>(42)->getName() << endl;
        else cout << "Can't fing matching item" << endl;
    
        cout << catalog.exists<Item>(1) << endl;
        cout << catalog.exists<Item>(2) << endl;
        cout << catalog.exists<Item>(3) << endl;
        cout << catalog.exists<Location>(1) << endl;
        cout << catalog.exists<Location>(2) << endl;
        cout << catalog.exists<Location>(3) << endl;
    
        cout << catalog.get<Item>(1)->getName() << endl;
        cout << catalog.get<Item>(2)->getName() << endl;
        cout << catalog.get<Location>(3)->getName() << endl;
    }
    

    Über Lob oder Kritik würde ich mich weiterhin freuen. Es lässt sich einfacher lernen, wenn man auf Fehler hingewiesen wird und diese dann in Zukunft vermeiden kann. Außerdem wäre ich auch weiterhin an Antworten auf die eine oder andere Frage aus den vorherigen Beiträgen interessiert, obwohl ich das meiste davon bereits wieder verworfen habe.

    Danke und Gruß,
    temi


Anmelden zum Antworten