<snip> big thread about polymorphic container ... </snip> I hope I didn't miss anything in the thread. If I'm repeating something, sorry. I don't think we want or need to limit what we put into the container. Neither by forcing certain virtual functions onto the base class, nor by limiting what the contained types can and can't do (like have pointers to themselves and do funky things in their copy/move constructors). When push_back<Triangle> is called, we create an instance of an ItemHandler<Triangle> class, that derives from BaseItemHandler, and implements copy/move virtually. ie type-erasure. ItemHandler<Triangle> knows how to move/copy Triangles. It is not Triangle's job! We put the ItemHandler<Triangle> in a map<RTTI, BaseItemHandler*>. Note: - we only need *one* ItemHandler<Triangle> for all Triangles, not one for each. - Triangle doesn't have any do_copy/move/size virtual functions, ItemHandler<Triangle> does. - we can store Triangle mixed in with Squares and other shapes or isolated in a group of Triangles. Maybe different containers will choose differently. - if stored mixed together, then we have a parallel vector that is a pointer to BaseItemHandler* for each item in the main vector. ie (typed in email, so should not compile) struct BaseItemHandler { virtual void do_copy(char * dest, char const * src) const = 0; virtual std::size_t size() const = 0; }; template <typename T> struct ItemHandler : BaseItemHandler { virtual void do_copy(char * dest, char const * src) const { T * typed_src = reinterpret_cast<T*>(src); new (dest) T(*typed_src); // in-place copy construct } virtual std::size_t size() const { return sizeof(T); } }; template <typename Item> void classifier::push_back(Item const & item) { char const * key = typeid(Item).name(); // or use raw name or address of type info // add/get handler to/from map HandlerMap::iterator itHandler = handlerMap.find(key); BaseItemHandler * handler = 0; if (itHandler == handlerMap.end()) { // new type we haven't seen before handler = new ItemHandler<Item>; handlerMap[key] = handler; } else { handler = *itHandler; } char * space = make_space_for_item(handler->size()); // make space in vector<char> handler->do_copy(space, item); inplace copy construct handlerList.push_back(handler); // handler for this item // note that handler is in handlerMap *once* (ie one per type) // and same pointer may be in handlerList multiple times, as it appears once for each item of type Item } classifier::iterator & classifier::iterator::operator++(int) { // iterator has pointer/iterator/offset into handlerList (called 'itHandler') BasItemHandler * handler = *itHandler; // and pointer/iterator/offset into vector<char>, called 'data' // ++ on data data += handler->size(); // ++ on handler ++itHandler; // iterator now points to next object in the vector, // and points to its associated handler return *this; } Tony On Tue, Aug 27, 2013 at 8:09 AM, Larry Evans <cppljevans@suddenlink.net>wrote:
On 08/27/13 06:44, Thorsten Ottosen wrote:
On 23-08-2013 17:08, Larry Evans wrote:
AFAICT, this shows the offset_ptr would solve the problem of moving the storage in case the storage needs to be resized.
Am I missing something?
I can't tell. Some interprocess experts might want to way in here?
Anyway, I can live with a container that has unstable pointers/references after push_back. std::vector<T> is like that, so what's exactly the difference here?
The offset_ptr<polymorophic_object> solves the unstable pointer problem caused by moving the storage buffer. That's one problem 1st mentioned by Rob Stewart here:
http://article.gmane.org/gmane.comp.lib.boost.devel/243582
and then again by Ben Pope here:
http://article.gmane.org/gmane.comp.lib.boost.devel/243633
The code I last posted shows the offset_ptr still points to the *this even after the move, although the raw pointer points to the old location. Also, no virtual methods are needed to preserve this stable pointer feature. Using just offset_ptr seems to do the job.
-regards, Larry
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost