Boost logo

Boost Users :

Subject: Re: [Boost-users] [Container] Forward declaration of movable types
From: Ion Gaztañaga (igaztanaga_at_[hidden])
Date: 2011-08-17 05:50:15


El 16/08/2011 19:05, Szymon Gatner escribió:

> So there is no really a way around it, is there? Either:
>
> 1) objects in container have to be kept by pointer to break dependency
> but then they
> have to be allocated on the heap so there is little or no benefit in
> making them movable
> (as smart pointer will provide necessary copy/move/ownership semantics)
>
> 2) whole container has to be pimpled so that hidden implementation may then take
> advantage of all move goodies like container emplacing
>
> I feel like 2nd option is the one that gives real benefits. Is that right?

Right.

>
> Also, I often write code like:
>
> class Widget
> {
> public:
> typedef std::vector<shared_ptr<MyMovable> > MyMovables;
>
> const MyMovables& movables() const;
>
> private:
>
> MyMovables movables_;
> }
>
> so that clients can later do:
>
> BOOST_FOREACH(MyMovable& m, indirect(widget->movables())
> {
> // do something with m
> }
>
> how to design Widget's class API in similar way if MyMovables is
> hidden behind pimpl?

//hpp

class MyMovable;

class Widget
{
   public:
     typedef std::vector<MyMovable> MyMovables;
     const MyMovables& movables() const;
   private:
     class Internals;
     Internals *impl_;
};

//cpp
#include "MyMovable.hpp"

const Widget::MyMovables& Widget::movables() const
{
   return impl_->movables_;
}

> PS. I just compiled such a code:
>
> //widget.hpp
>
> class Movable; // only forward declared
>
> class Widget
> {
> boost::container::vector<Movable> movables_;
> }
>
> and widget.cpp properly adds Movable instances by moving them to movable_.
>
> Why does this work? If this is normal then I have no problem at all ;)

Because you haven't instantiated the type. This does not compile:

#include<boost/container/vector.hpp>

class Movable; // only forward declared
class Widget
{
   boost::container::vector<Movable> movables_;
};

int main()
{
    Widget w;
}

However, I just checked that if you put all the functions in a cpp it
will work fine. I think you've discovered a great Boost.Container
feature derived from the care I put to support recursive types and avoid
too early Movable instantiations:

//hpp

#include<boost/container/vector.hpp>

class Movable; // only forward declared
class Widget
{
    boost::container::vector<Movable> movables_;
    public:
    Widget(const Widget &);
    Widget &operator= (const Widget &);
    Widget();
    ~Widget();
};

//cpp

//here implement constructor/destructor/assignment...

The difference with pimpl is that you need to include "vector.hpp", with
pimpl, you don't need to.

Best,

Ion


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net