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.