C++ Reference to vector of derived types -
i have numerous objects implementing interface called exposescommands
.
class exposescommands { virtual bool get_command_results(std::string command, std::vector<std::string> &results) = 0; }; typedef std::unique_ptr<exposescommands> exposescommands_ptr;
commands exposed via template class:
template <typename t> class exposedcommands : public exposescommands { private: static std::map<const char*, std::string t::*, cmp_str> exposed_cmds; public: virtual bool get_command_results(std::string command, std::vector<std::string> &results); }
now, trying add sub-commands. sub-commands link sub-objects implement commands. way add them so:
template <typename t> class exposedcommands : public exposescommands { private: static std::map<const char*, std::string t::*, cmp_str> exposed_cmds; static std::map<const char*, std::vector<exposescommands_ptr> t::*, cmp_str> exposed_sub_cmds; public: virtual bool get_command_results(std::string command, std::vector<std::string> &results) { auto &it = exposed_cmds.find(command.c_str()); if (it != exposed_cmds.cend()) { auto x = std::bind(it->second, std::placeholders::_1); std::string data = x(*((t*)this)); if (data != "") { results.push_back(data); } return true; } // else check if in exposed_sub_cmds. // if so, iterate through vector, call get_command_results // on remainder of command name each sub object, adding // result vector of results. // return true // return false; } }
i have objects implementing interface (building of maps not shown here):
class objecta : public exposescommands<objecta> { public: std::string cmd_x; // command x std::string cmd_y; // command y } typedef std::unique_ptr<objecta> objecta_ptr; class objectb { public: std::string cmd_z; // command z std::vector<objecta_ptr> my_as; // 'objecta' sub commands }
unfortunately, doesn't work because can't assign &std::vector<objecta_ptr>
std::vector<exposescommands_ptr> t::*
.
is there way around this? or better approach problem?
to summarize problem: have base class , derived classes
class base { public: virtual ~base(); }; class derived1 : public base; class derived2 : public base;
you need store collection of pointers (for ownership management chose use std::unique_ptr
, seems wise) derived1
objects in way can used code doesn't know derived1
exists, , wants use properties of base
, not want lose property specific collection of base
objects contains derived1
objects only. kind of type erasure, runtime behaciour of collection should not depend on whether stores base
, derived1
or derived2
objects (or mixture of it, property gets erased), yet @ compile time, don't want write ugly downcasts (and want compiler verify downcast objects container statically know contain derived1
objects). aware if going store pointers derived1
in std::unique_ptr<base>
, absolutely necessary base
has virtual destructor.
i don't know ready-made solution off-hand (it couldn't find skimming on boost libraries tagged container, too), can show how reach goal yourself. need template, different compile-time types (just std::vector
template), internally stores data in fixed type. this:
typedef std::unique_ptr<base> base_ptr; template <typename t> class basevector { public: const std::vector<base_ptr> & as_baseclass_vector() const { return backing_; } private: std::vector<base_ptr> backing_; };
note as_baseclass_vector return const reference raw vector, because result must not used insert objects of wrong type (e.g. pointers derived2
objects) commandvector
instantiated derived1
. half way go, other half sadly reimplementing standard library container concept on vector-wrapper, along this:
template<typename t> void commandvector::push_back(std::unique_ptr<t> obj) { backing_.push_back(std::move(obj)); }
or, more importantly , interestingly:
template<typename t> const t* basevector::operator[](size_t index) const { return static_cast<t*>(backing_[index]); }
note operator[]
not return reference-to-unique_ptr
, return reference unique_ptr<base>
, because stored in backing vector. if created tempory unique_ptr
t
, have remove ownership vector - not want that! result has been declared const, because returns copy instead of usual reference, , modifying return value (which forbidden) not modify object in vector, opposed users expect. have reimplement other methods (iterators quite interesting, can based on boost::transform_iterator
) if chose go route.
Comments
Post a Comment