10 thoughts on “GotW #100: Solution

  1. “The chief drawbacks are that it requires an extra wrapper function call and normally makes the visible class useless for inheritance.”

    If you’re invoking the pimpl idiom, chances are the class was useless for inheritance before you even started.

    Not a criticism, just a statement of the (perceived) fact.

  2. @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.

  3. 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?

  4. 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

    pimpl->func(this, params)
    to
    func(this, params)

    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.

  5. 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.

  6. Under the solution for question 2:

    “You still need to write the visible class’ destructor yourself and define it out of line in the implementation class”

    I believe you mean “implementation file” here.

  7. 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.

    Thanks.

  8. Couldn’t find an alternative link for the solution (link broken). Are you still maintaining pages for these older articles?

  9. 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.

    See also /gotw.

Comments are closed.