Boost logo

Boost :

Subject: Re: [boost] Pimpl Again?
From: Emil Dotchevski (emildotchevski_at_[hidden])
Date: 2016-05-31 17:10:35


On Tue, May 31, 2016 at 12:09 PM, Chris Glover <c.d.glover_at_[hidden]> wrote:

> I sometimes don't pimpl an entire object. This might be because I have
> templates in the interface or because I need the functions to inline. Your
> solution doesn't allow me to do that.
>

I agree that being able to un-pimple a subset of the members in the face of
profiler evidence that inlining is necessary is important. I'm not sure why
do you say that "my approach" doesn't support that. One possibility is to
use inheritance in the cpp file:

header:

struct foo { int critical_; };
shared_ptr<foo> create_foo();
inline void use_foo_critical( foo * p ) { ++p->critical_; }
void use_foo_not_so_critical( foo * );

cpp:

namespace
{
  struct foo_: foo
  {
    int not_so_critiral_;
  };
}

shared_ptr<foo> create_foo()
{
  return shared_ptr<foo>(new foo_);
}

void use_foo_not_so_critical( foo * p )
{
  foo_ * q=static_cast<foo_ *>(p);
  ++q->not_so_critical_;
}

> It also forces a dynamic allocation which we already discussed could be
> avoided by using an internal buffer.
>

This is actually the main motivation for using shared_ptr directly in the
header -- to allow for custom allocators in the create_foo function, which
can completely eliminate dynamic allocations. Generally, if you're
concerned about dynamic allocations yet you're not using shared_ptr, you're
doing it wrong. :)

If we didn't care about this point of control, then it'd be more portable
to remove shared_ptr from the header and simply define a C interface:

struct foo;
foo * create_foo();
void destroy_foo( foo * );

(In this case a C++ user can still use shared_ptr with a custom deleter, at
the cost of an extra allocation.)

OTOH do note that in the header we may leave shared_ptr incomplete and
still declare a shared_ptr factory function. This leads to extremely lean
header files:

namespace boost { template <class> class shared_ptr; }
struct foo;
boost::shared_ptr<foo> create_foo();
void use_foo( foo * );

Emil


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