Boost logo

Boost :

Subject: Re: [boost] [cpo-proposal] presentation of the idea
From: Gottlob Frege (gottlobfrege_at_[hidden])
Date: 2013-08-28 00:51:48


<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_at_[hidden]>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
>


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk