Boost logo

Boost :

Subject: Re: [boost] [pimpl] Mini Review
From: Krzysztof Czainski (1czajnik_at_[hidden])
Date: 2011-05-27 08:00:55


2011/5/27 Vladimir Batov <vb.mail.247_at_[hidden]>

> > Krzysztof Czainski <1czajnik <at> gmail.com> writes:
> > ...
> > Personally I think the proposed Pimpl library tries to solve too many
> things
> > at once.
>
> On the bigger scale it tries just *one* thing -- to implement the Pimpl
> idiom as
> it is understood by me (which might well be misunderstanding).

I take your point here.

> On the smaller
> scale it tries to do *two* things -- 1) the separation of interface and
> implementation and 2) implementation hiding. It is because that is how I
> understand the properties/qualities/characteristics of the Pimpl idiom.
> What
> exactly more does it do? Is it the relational ops you do not like? Then,
> say,
> shared_ptr has them and one needs them if a Pimpl-based class is to be
> used,
> say, in std::containers. Is it null() that keeps you awake at night? Then,
> many
> classes (like shared_ptr again) have it... maybe not in as explicit form
> but
> still. Is it the support for the Bridge pattern and Non-Virtual Interface
> Idiom
> that get you worried? Then, ignore that -- that's not a stone in your shoe,
> is
> it?
>

Suppose i write a class:

class Gadget
{
public:
  Gadget();
  int fun();
private:
  int x;
};

Now later I decide, that it would be nice to use ExpenciveGadget in the
implementation of my Gadget. But it's expensive, so I don't want my users
(people who include Gadget.h) to pay for it (have it inculded together). So
the first thin I think is, hay, Pimpl ;-)

option a) (assuming we have a clone_ptr)

class Gadget
{
public:
  Gadget();
  int full();
private:
  struct Impl;
  clone_ptr<Impl> impl_; // now I moved int x into impl_ too, but it's
irrelevant right now
};

option b)
class Gadget : public pimpl<Gadget>::value_semantics
{
public:
  Gadget();
  int full();
};

Now the question is what else, besides my pointer to implementation, did I
inherit form pimpl<Gadget>::value_semantics? And the answer is some more
interface. operator<, operator safebool, null(), etc. I didn't want to
extend my interface, but I got it for free. And all I'm saying is it can be
bad even though usually it doesn't matter.

Why bad?

1) Tyops:
Gadget a; Madget b; // suppose Gadget is the above, and can't be null, but
Madget can be null
if ( a.null() /*oops, I ment a.full()*/ ) ...
or
if ( a /* oops, I ment b */ ) ...

2) template < class T > void abc( typename enable_if<
has_operator_less_then<T> >::type* = 0 ) {...}
template < class T > void abc( typename disable_if<
has_operator_less_then<T> >::type* = 0 ) {...}

Gadget g;
abc(g); // now I want the second version of abc.. which gets called?

Now you say shared_ptr has these operators, and what if I don't need them?
Well, I don't inherit from shared_ptr when I decide to use it in my
implementation. I make it a member, and the operators don't get exposed
outside.

3) Don't pay for what you don't need. I just want to hide my implementation,
while I get the unnecessary operators< etc. Ok, I take your point about
regex below, that this argument is weak, but I think the two arguments above
sitll stand.

> > Individual use cases might want those, not care about them, or
> > specifically not want them.
>
> So, if I follow your line of reasoning correctly, then I should discard
> boost::regex as it provides support for
>
> Perl Regular Expression Syntax
> POSIX Extended Regular Expression Syntax
> POSIX Basic Regular Expression Syntax
>
> when I only "want/care for" the Perl syntax? Do you pay for that additional
> functionality? Is it heavy to carry? Is it getting in your way somehow?
> Does it
> result in unexpected behavior? Have you noticed that *any* library actually
> provides *more* than *you* usually need because such library might be
> written
> with wider audience in mind? Jeez, I do not believe we are even discussing
> it!
>
> > ...
> > And Pimpl providing the following:
> > safebool operator;
> > pimpl::null;
> > can be an unwanted side-effect, and may therefore lead to a decision not
> to
> > use the proposed Pimpl in this case.
>
> Are you just pondering or have something concrete in mind? If that is the
> latter, then bring it on. We'll look at it and fix it... or I'll say, shit,
> you
> are right, bad-bad design... and fix it again. Otherwise, all these "can"
> and
> "may" are just noise.
>
> > Many of the features addressed by Pimpl can be provided by separate
> tools,
> > instead of packing all of them to Pimpl.
>
> Yeah, and next time you go to buy, say, a car, please to not accept a car
> as a
> whole but insist on wheels, radio, etc. separately. I am sure you'll enjoy
> the
> ride.
>
> > ...
> > To conclude, I agree, that the problems addressed by the proposed Pimpl
> need
> > solutions, but I suggest providing separate tools addressing the problems
> > instead of Pimpl addressing all of these.
>
> So, would you please come forward and suggest something tangible addressing
> those problems. I am sure you are prepared that that features that you care
> about might not be so dear to somebody else's heart.
>
> V.
>

I hope you'll judge it with no hard feelings, Vladimir ;-)

Regards
Kris


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