@Mike: Not necessarily. Nearly every base class has private methods and state. If for a transitively popular base class those private parts are still changing (e.g., during the development cycle), or for any base class the base size/layout must be able to change in the future without more than a relink (e.g., to avoid the fragile base class problem), Pimpl makes lots of sense.
Any comment on the advantages or otherwise of declaring a const pointer to pimpl (i.e. “const unique_ptr pimpl;”)?
AIUI, this means that the compiler can detect accidental assignment to the pointer. It’s obviously not appropriate if you want a move constructor, I guess. Anything else to consider for or against making it const?
[...] This is Microsoft’s first native-code-only developer event in years, and it’s not limited to Microsoft products or technologies – it’s about ISO C++ on all platforms. We’re taking the initiative to put on this event because we know that there’s a huge demand for information about the new ISO C++11 standard, but that information is still really hard to come by – the standard was just published last month, none of the major books have been updated yet to reflect it, and high-quality public information is just starting to trickle out (I’m trying to do my part too). [...]
Why not just make the unique_ptr public and implement the internal functions as anonymous namespace free functions in widget.cpp that take a widget* this pointer when called by the public functions in widget?
Would this not clear up the back-pointer situation and reduce
Eliminating a potential error of passing the wrong this/pimpl pair (pimpl->add(rhs, this) doesn’t look that wrong and will compile).
This reduces pimpl entirely to an RAII version of the C handle idiom: a pointer to a incomplete type with a set of public functions in header files with external linkage, and a set of implementation details with internal linkage. It’s a mainstay of OO APIs in C.
You’d have to revert to the more complicated version if you wanted to have protected data members, but those are discouraged in most code styles anyway.
I have used a variation of the pimpl theme for base classes. Basically, similar to how you might implement inheritence in C, I created public and private headers of the same class. The public has the class definition, with it’s pointer to a pimpl. The private header contains a declaration of that pimpl. The public class then becomes little more than a wrapper and to inherit you actually only need to create new pimpl derivatives and possibly some overrides for creation.
I would admit though that this has limited uses, but it’s served some important niche cases for me.
Where you have,
“However, it does mean adding an extra parameter to each hidden function.”
did you mean to say something like,
“However, it does mean adding an extra parameter to each hidden function that needs to access the visible class.”?
As stated now, “each hidden function” seems to imply every hidden function, but it seems an advantage worth making explicit that this second approach flexibly allows using it only with those hidden functions that actually need the special access.
About the widget constructor’s initializer list, I’m not used to seeing the curly braces, especially since it doesn’t involve an aggregate/list. Would simple parens still work? If so, is the use of curly braces just a stylistic preference or is there an advantage/reason to preferring them? Other things being equal, I would guess that use of simple parens would give more portable code that is acceptable to more compilers, but perhaps there is a compensating benefit to the curly braces.
I took down those temporary pages for GotWs #100-104 for a few weeks as GotW was getting underway again to avoid confusion as I generate new ones. I’ve now restored them exactly where they were, and as I revise them for C++14 I’m replacing the page contents with a redirect/link to the permanent version.