On Sun, May 29, 2016 at 10:47 PM, Vladimir Batov < Vladimir.Batov@constrainttec.com> wrote:
On 2016-05-30 12:36, Emil Dotchevski wrote:
My 2c:
In foo.h, instead of
class foo { class pimpl pimpl * p_; public: foo(); ~foo(); void do_something(); };
It's better to do it the C way: simply leave foo incomplete:
struct foo; foo * create_foo(); void destroy_foo( foo * ); void do_something( foo * );
The above is much improved using shared_ptr:
struct foo; shared_ptr<foo> create_foo(); void do_something( foo * );
If you are saying that pimpl is conceptually simple, then I agree. std::unique_ptr is conceptually simple as well.
If you are saying that the snippets you provided are sufficient, then I have to disagree. Say, pimpl in the context of polymorphic hierarchies or value pimpls come to mind.
Value pimpl, sure, if you need it.
Polymorphism -- the snippets I provided are sufficient, virtual function
calls work just fine. For example, in the CPP file you could define
do_something (see above declaration) like so:
void do_something( foo * p )
{
p->do_something(); //virtual
}
Implicit/static and dynamic casts between polymorphic types work just as
well, since the types left incomplete in the header file are complete in
the cpp file. For example, in the header we could say:
struct foo;
struct bar;
bar * to_bar( foo * );
foo * to_foo( bar * );
And in the cpp:
struct bar
{
....
};
struct foo: bar
{
....
};
bar * to_bar( foo * p )
{
return p;
}
foo * to_foo( bar * p )
{
assert(dynamic_cast