diff --git a/CppCoreGuidelines.md b/CppCoreGuidelines.md
index ecbe6dd..eeb25dd 100644
--- a/CppCoreGuidelines.md
+++ b/CppCoreGuidelines.md
@@ -1202,6 +1202,7 @@ Interface rule summary:
* [I.24: Avoid adjacent unrelated parameters of the same type](#Ri-unrelated)
* [I.25: Prefer abstract classes as interfaces to class hierarchies](#Ri-abstract)
* [I.26: If you want a cross-compiler ABI, use a C-style subset](#Ri-abi)
+* [I.27: For stable library ABI, consider the Pimpl idiom](#Ri-pimpl)
* [I.30: Encapsulate rule violations](#Ri-encapsulate)
See also
@@ -2139,6 +2140,53 @@ If you use a single compiler, you can use full C++ in interfaces. That may requi
(Not enforceable) It is difficult to reliably identify where an interface forms part of an ABI.
+### I.27: For stable library ABI, consider the Pimpl idiom
+
+##### Reason
+
+Because private data members participate in class layout and private member functions participate in overload resolution, changes to those
+implementation details require recompilation of all users of a class that uses them. A non-polymorphic interface class holding a pointer to
+implementation (Pimpl) can isolate the users of a class from changes in its implementation at the cost of an indirection.
+
+##### Example
+
+interface (widget.h)
+
+ class widget {
+ class impl;
+ std::unique_ptr pimpl;
+ public:
+ void draw(); // public API that will be forwarded to the implementation
+ widget(int); // defined in the implementation file
+ ~widget(); // defined in the implementation file, where impl is a complete type
+ widget(widget&&) = default;
+ widget(const widget&) = delete;
+ widget& operator=(widget&&); // defined in the implementation file
+ widget& operator=(const widget&) = delete;
+ };
+
+
+implementation (widget.cpp)
+
+ class widget::impl {
+ int n; // private data
+ public:
+ void draw(const widget& w) { /* ... */ }
+ impl(int n) : n(n) {}
+ };
+ void widget::draw() { pimpl->draw(*this); }
+ widget::widget(int n) : pimpl{std::make_unique(n)} {}
+ widget::~widget() = default;
+ widget& widget::operator=(widget&&) = default;
+
+##### Notes
+
+See [GOTW #100](https://herbsutter.com/gotw/_100/) and [cppreference](http://en.cppreference.com/w/cpp/language/pimpl) for the trade-offs and additional implementation details associated with this idiom.
+
+##### Enforcement
+
+(Not enforceable) It is difficult to reliably identify where an interface forms part of an ABI.
+
### I.30: Encapsulate rule violations
##### Reason
@@ -6851,7 +6899,7 @@ Since each implementation derived from its interface as well as its implementati
As mentioned, this is just one way to construct a dual hierarchy.
-Another (related) technique for separating interface and implementation is [PIMPL](#???).
+Another (related) technique for separating interface and implementation is [Pimpl](#Ri-pimpl).
##### Note
@@ -15563,7 +15611,7 @@ through non-`const` pointers.
It is the job of the class to ensure such mutation is done only when it makes sense according to the semantics (invariants)
it offers to its users.
-See also [PIMPL](#???).
+See also [Pimpl](#Ri-pimpl).
##### Enforcement
@@ -17354,7 +17402,7 @@ The `Link` and `List` classes do nothing but type manipulation.
Instead of using a separate "base" type, another common technique is to specialize for `void` or `void*` and have the general template for `T` be just the safely-encapsulated casts to and from the core `void` implementation.
-**Alternative**: Use a [PIMPL](#???) implementation.
+**Alternative**: Use a [Pimpl](#Ri-pimpl) implementation.
##### Enforcement
diff --git a/scripts/hunspell/isocpp.dic b/scripts/hunspell/isocpp.dic
index 7f83d2f..7b2c1ef 100644
--- a/scripts/hunspell/isocpp.dic
+++ b/scripts/hunspell/isocpp.dic
@@ -101,6 +101,7 @@ CplusplusCS
cpp
cpp98
CppCon
+cppreference
CRTP
cst
cstdarg
@@ -193,6 +194,7 @@ GFM
Girou
github
GitHub
+GOTW
gp
GPLv3
gsl
@@ -219,6 +221,7 @@ ifdef
iff
ifstream
impactful
+impl
Impl
incompleat
increment1
@@ -366,7 +369,8 @@ pb2
pc
performant
pessimization
-PIMPL
+pimpl
+Pimpl
Pirkelbauer
PL4
PLDI