There have been a few questions on SO about the pimpl idiom, but I'm more curious about how often it is leveraged in practice.
I understand there are some trade-offs between performance and encapsulation, plus some debugging annoyances due to the extra redirection.
With that, is this something that should be adopted on a per-class, or an all-or-nothing basis? Is this a best-practice or personal preference?
I realize that's somewhat subjective, so let me list my top priorities:
- Code clarity
- Code maintainability
- Performance
I always assume that I will need to expose my code as a library at some point, so that's also a consideration.
EDIT: Any other options to accomplish the same thing would be welcome suggestions.
pImpl will work best when we have r-value semantics.
The "alternative" to pImpl, that will also achieve hiding the implementation detail, is to use an abstract base class and put the implementation in a derived class. Users call some kind of "factory" method to create the instance and will generally use a pointer (probably a shared one) to the abstract class.
The rationale behind pImpl instead can be:
Semantics of the container class for the pImpl could be: - Non-copyable, not assignable... So you "new" your pImpl on construction and "delete" on destruction - shared. So you have shared_ptr rather than Impl*
With shared_ptr you can use a forward declaration as long as the class is complete at the point of the destructor. Your destructor should be defined even if default (which it probably will be).
swappable. You can implement "may be empty" and implements "swap". Users can create an instance of one and pass a non-const reference to it to get it populated, with a "swap".
2-stage construction. You construct an empty one then call "load()" on it to populate it.
shared is the only one I have even a remote liking for without r-value semantics. With them we can also implement non-copyable non-assignable properly. I like to be able to call a function that gives me one.
I have, however, found I tend more now to use abstract base classes more than pImpl, even when there is only one implementation.
This idiom helps greatly with compile time on large projects.
External link
This is good too