Pimpl framework comments/suggestions

Hi All
I've been experimenting with pimpl recently. What I've seen written about
the pimpl idiom is that you have an interface class and an implementation
class, and in the interface class you put some kind of pointer to the
implementation.
However, I thought, sometimes you might want that to be a shared pointer. Or
an intrusive pointer. Or unique pointer. Or maybe sometimes you might decide
not to use pimpl at all.
I thought it was a bit silly that you had to make these decisions at the
time you create the interface class. I thought it would be nice if you could
write the interface independent of how it was going to be connected to the
implementation, and then hook them together however you like.
So this is what I've done. Basically I've broke things up into three
separate parts:
(1) Interface
(2) Implementation
(3) What joins them together (i've created unique_pimpl and shared_pimpl as
examples)
I've implemented a unique_ptr and shared_ptr pimpl implementations as
examples. The idea is that you can basically do this:
unique_pimpl

On 04/14/2011 11:32 PM, Clinton Mead wrote:
Hi All
I've been experimenting with pimpl recently. What I've seen written about the pimpl idiom is that you have an interface class and an implementation class, and in the interface class you put some kind of pointer to the implementation.
However, I thought, sometimes you might want that to be a shared pointer. Or an intrusive pointer. Or unique pointer. Or maybe sometimes you might decide not to use pimpl at all.
I thought it was a bit silly that you had to make these decisions at the time you create the interface class. I thought it would be nice if you could write the interface independent of how it was going to be connected to the implementation, and then hook them together however you like.
So this is what I've done. Basically I've broke things up into three separate parts:
(1) Interface (2) Implementation (3) What joins them together (i've created unique_pimpl and shared_pimpl as examples)
I've implemented a unique_ptr and shared_ptr pimpl implementations as examples. The idea is that you can basically do this:
unique_pimpl
::create(...) or shared_pimpl ::create(...) make_your_own ::create(...) for any interface and implementation you choose.
I've included all the code in a question at http://stackoverflow.com/questions/5666442 but it doesn't seem to be getting much attention there, so I thought I'd bring it up on this list.
If something like this isn't in Boost, and people like it, with a bit of help I'd be happy to work on it to get it into Boost. Alternatively I'm happy for someone else to Boostify this. I've used a bit of c++0x in the code, gcc 4.4.5 will compile it though.
However if I'm just (badly) reinventing the wheel, if someone could direct me to where this has already been done that would be good to.
Hi Clinton, The point of a Pimpl is that the user never knows or cares that it is a Pimpl -- it's just another object. Pimpl is a very small implementation detail. With this code, that detail is no longer very small -- the user needs to know too much about how the object was implemented. While Pimpl initially stood for "pointer to implementation", a better way to think about it is "private implementation". The implementation is completely hidden from the user (and the compiler). With your proposal, a significant part of the implementation is no longer private. In fact, it has leaked into the interface. Take a look at this article for good insights into Pimpl and another approach: http://drdobbs.com/cpp/205918714 I still think this adds more complexity to Pimpl than is warranted. But, if I had to implement dozens of such classes for a library, I might change my mind... Regards, Rob

Hi Rob
I don't really understand what you mean by this. What part of the
implementation has leaked into the interface?
Maybe I've missed the point but what I'm trying to achieve is the opposite.
With all the implementations of pimpl I've seen, the "pointer" is leaked
into the interface. I'm just trying to unleak it and separate it. The idea
is that people can write interfaces without having to specify how pimpl is
actually implemented.
Is there another way to do this which is simpler?
Clinton
On Mon, Apr 18, 2011 at 2:24 AM, Rob Riggs
On 04/14/2011 11:32 PM, Clinton Mead wrote:
Hi All
I've been experimenting with pimpl recently. What I've seen written about the pimpl idiom is that you have an interface class and an implementation class, and in the interface class you put some kind of pointer to the implementation.
However, I thought, sometimes you might want that to be a shared pointer. Or an intrusive pointer. Or unique pointer. Or maybe sometimes you might decide not to use pimpl at all.
I thought it was a bit silly that you had to make these decisions at the time you create the interface class. I thought it would be nice if you could write the interface independent of how it was going to be connected to the implementation, and then hook them together however you like.
So this is what I've done. Basically I've broke things up into three separate parts:
(1) Interface (2) Implementation (3) What joins them together (i've created unique_pimpl and shared_pimpl as examples)
I've implemented a unique_ptr and shared_ptr pimpl implementations as examples. The idea is that you can basically do this:
unique_pimpl
::create(...) or shared_pimpl ::create(...) make_your_own ::create(...) for any interface and implementation you choose.
I've included all the code in a question at http://stackoverflow.com/questions/5666442 but it doesn't seem to be getting much attention there, so I thought I'd bring it up on this list.
If something like this isn't in Boost, and people like it, with a bit of help I'd be happy to work on it to get it into Boost. Alternatively I'm happy for someone else to Boostify this. I've used a bit of c++0x in the code, gcc 4.4.5 will compile it though.
However if I'm just (badly) reinventing the wheel, if someone could direct me to where this has already been done that would be good to.
Hi Clinton,
The point of a Pimpl is that the user never knows or cares that it is a Pimpl -- it's just another object. Pimpl is a very small implementation detail. With this code, that detail is no longer very small -- the user needs to know too much about how the object was implemented.
While Pimpl initially stood for "pointer to implementation", a better way to think about it is "private implementation". The implementation is completely hidden from the user (and the compiler). With your proposal, a significant part of the implementation is no longer private. In fact, it has leaked into the interface.
Take a look at this article for good insights into Pimpl and another approach: http://drdobbs.com/cpp/205918714
I still think this adds more complexity to Pimpl than is warranted. But, if I had to implement dozens of such classes for a library, I might change my mind...
Regards,
Rob
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users

On 04/17/2011 10:49 AM, Clinton Mead wrote:
I don't really understand what you mean by this. What part of the implementation has leaked into the interface?
Hi Clinton, What leaks is the implementation of the Pimpl itself. A Pimpl consists of two distinct things: the interface (which the user cares about), and the pointer (which the user need not know about). The user should not know or care that a class is implemented as a Pimpl.
Maybe I've missed the point but what I'm trying to achieve is the opposite. With all the implementations of pimpl I've seen, the "pointer" is leaked into the interface. I'm just trying to unleak it and separate it. The idea is that people can write interfaces without having to specify how pimpl is actually implemented.
It seems to me that this flexibility is for the benefit of the Pimpl
writer, and at the expense of the Pimpl user.
From your example code:
|
unique_pimpl

Isn't this much simpler and more natural for the user:
unique_ptr<Klass> foo(new Klass);
It is, but doesn't this require Klass here to be a complete type? Is Klass the interface or the implementation? If Klass is the implementation, how does this hide the implementation? And if Klass is the interface, won't it need to contain another pointer, which would result in following two pointers instead of one for all method calls?

On 04/17/2011 07:10 PM, Clinton Mead wrote:
And if Klass is the interface, won't it need to contain another pointer, which would result in following two pointers instead of one for all method calls?
Who cares? It's a reasonable price for what Pimpl buys you. The price of that encapsulation is a little indirection. With the added benefit that it can be used as a plain old value type (no pointer, except the one hidden inside). If that cost is too much to bear, Pimpl isn't the right answer in the first place. I think you might be missing the point about why Pimpl is such a rockin' cool idea. It is an extremely simple mechanism for ensuring ABI stability. If it's no longer dead simple, it completely loses its charm; it becomes harder to maintain a stable ABI. Library writers don't want that.
participants (2)
-
Clinton Mead
-
Rob Riggs