PImpl Idiom
First introduced in CS247.
Links
- https://en.cppreference.com/w/cpp/language/pimpl
- https://www.geeksforgeeks.org/pimpl-idiom-in-c-with-examples/
- https://stackoverflow.com/questions/5576922/should-i-use-shared-ptr-or-unique-ptr
OMG I saw this in NVIDIA codebase!!
Use Case #1: Ensure Strong Guarantee
Introduced after diving into Exception Safety, and how other methods couldn’t work for strong guarantee.
struct CImpl { // "Impl" class has the fields
A a;
B b;
};
class C {
unique_ptr<CImpl> pImpl;
public:
void f() {
unique_ptr<CImpl> temp = make_unique<CImpl>(*pImpl);
temp->a.g();
temp->b.h();
std::swap(temp, pImpl); // guaranteed nothrow
}
};
This is the strong guarantee - if a.g()
or b.h()
throw - all work is done on temp
, so we’re fine.
Otherwise, swap will always succeed f
will do its job.
Use Case 2: Reduce Compilation Dependencies
PImpl Idiom can also be used in some scenarios for reducing compilation dependencies.
Typically:
C.h
class C {
A a; // If any of the private fields change, anbody who #include "C.h" must recompile
B b;
};
On the other hand:
CImpl.h
struct CImpl {
A a;
B b;
};
C.h
class CImpl;
class C {
unique_ptr<CImpl> pImpl;
...
};
Now, if cImpl
changes only C.cc
must recompile. Because we only use a forward declaration in C.h
no recompilation.
Finally - we could make CImpl
a polymorphic class - swap out implementations at runtime - the Bridge Pattern.