Container für mehrere Typen auf einmal



  • Hallo 🙂
    Ich habe im Versuch einen Container zu schreiben, der Objekte von verschiedenen Typen gleichzeitig beinhalten kann, folgende Klassen geschrieben. Hier erstmal der Code :

    #ifndef I_PROPERTY_HPP
    #define I_PROPERTY_HPP
    
    #include <string>
    #include <typeindex>
    #include <type_traits>
    
    class IProperty
    {
    	public:
    		IProperty(const std::string id, const std::type_index t_index);
    		virtual ~IProperty();
    
    		const std::string     getId()        const;
    		const std::type_index getTypeIndex() const;
    
    	protected:
    	private:
    		const std::string     id_;
    		const std::type_index t_index_;
    
    }; // class IProperty
    
    #endif // I_PROPERTY_HPP
    
    #include "IProperty.hpp"
    
    IProperty::IProperty( const std::string id, const std::type_index t_index)
    	: id_(id), t_index_(t_index)
    {}
    
    IProperty::~IProperty()
    {}
    
    const std::string IProperty::getId() const
    {
    	return id_;
    }
    
    const std::type_index IProperty::getTypeIndex() const
    {
    	return t_index_;
    }
    
    #ifndef T_PROPERTY_HPP
    #define T_PROPERTY_HPP
    
    #include <typeindex>
    
    #include "IProperty.hpp"
    
    template < typename Type > 
    class TProperty : public IProperty
    {
    	public:
    		TProperty(const std::string id) : IProperty(id, std::type_index(typeid(Type))){}
    
    		Type getValue()           const { return value_; }
    		void setValue(Type value)       { value_ = value; }
    
    	protected:
    	private:
    		Type value_;
    
    }; // class TProperty
    
    #endif // T_PROPERTY_HPP
    
    #ifndef PROPERTY_MANAGER_HPP
    #define PROPERTY_MANAGER_HPP
    
    #include <iostream>
    #include <functional>
    #include <map>
    #include <memory>
    #include <stdexcept>
    #include <string>
    
    #include "IProperty.hpp"
    #include "TProperty.hpp"
    
    class PropertyManager
    {
    	public: 
    		PropertyManager();
    
    		template < typename Type > 
    		Type getPropertyValue(const std::string id) const {
    			if (properties_.find(id) != properties_.end()){
    				return std::dynamic_pointer_cast<TProperty<Type>>(properties_.at(id))->getValue();
    			}
    			throw std::invalid_argument("Property \"" + id + "\" not found!");
    		}
    
    		template < typename Type > 
    		void setPropertyValue(const std::string id, Type value){
    			if (properties_.find(id) != properties_.end()){
    				std::dynamic_pointer_cast<TProperty<Type>>(properties_.at(id))->setValue(value);
    			} else
    			throw std::invalid_argument("Property \"" + id + "\" not found!");
    		}
    
    		template < typename Type >
    		void addProperty(const std::string id, Type value){
    			if (properties_.find(id) == properties_.end()){
    				properties_.emplace(id, std::make_shared<TProperty<Type>>(id));
    				std::dynamic_pointer_cast<TProperty<Type>>(properties_.at(id))->setValue(value);
    			} else
    			throw std::invalid_argument("Property \"" + id + "\" already exists!");
    		}
    
    		std::function<void(const std::string, bool)>   addBool;
    		std::function<void(const std::string, char)>   addChar;
    		std::function<void(const std::string, int)>    addInt;
    		std::function<void(const std::string, float)>  addFloat;
    		std::function<void(const std::string, double)> addDouble;
    
    	protected:
    	private:
    		std::map<const std::string, std::shared_ptr<IProperty>> properties_;
    
    }; // class PropertyManager
    
    #endif //PROPERTY_MANAGER_HPP
    
    #include "PropertyManager.hpp"
    
    PropertyManager::PropertyManager()
    	: addBool   { std::bind(&PropertyManager::addProperty<bool>,   this, std::placeholders::_1, std::placeholders::_2) },
    	  addChar   { std::bind(&PropertyManager::addProperty<char>,   this, std::placeholders::_1, std::placeholders::_2) },
    	  addInt    { std::bind(&PropertyManager::addProperty<int>,    this, std::placeholders::_1, std::placeholders::_2) },
    	  addFloat  { std::bind(&PropertyManager::addProperty<float>,  this, std::placeholders::_1, std::placeholders::_2) },
    	  addDouble { std::bind(&PropertyManager::addProperty<double>, this, std::placeholders::_1, std::placeholders::_2) }
    {}
    

    Jetzt habe ich zwei Fragen.
    Erstens, ist die Umsetzung des Containers grundsätzlich akzeptabel oder gibt es eine effektivere Methode dies zu erreichen ?
    Zweitens, im letzten Codeblock initialisiere ich die "Synonyme" für die Funktion
    "addProperty". Gibt es hier auch eine andere Möglichkeit dies umzusetzen ? ( typedef scheint keine Option zu sein )



  • Nach IProperty hab ich aufgehört:
    - I, dann aber keine abstrakten Funktionen - merkwürdig
    - call by value im Konstruktor, aber const?
    - const Returnwerte, die weder Referenz noch Pointer sind?
    - const Member?



  • Was ist der Zweck von dem ganzen? Wenn du verschiedene Typen speichern willst, könntest du boost::variant oder boost::any verwenden (bzw., es gibt bessere Klassen als boost::any, das hat keine Optimierung für kleine Typen). Was du gemacht hast, schaut schon so ein bisschen wie boost::any aus, aber ziemlich schlecht umgesetzt.


Log in to reply