For details and explanations see the Non-Virtual Interface idiom in [11] and Rule #39 in [12].
struct Book : boost::impl_ptr<Book>::shared // Not virtual { Book(args); string const& title() const; string const& author() const; }; template<> struct boost::impl_ptr<Book>::implementation { implementation(args) {...} virtual ~implementation() {...} } struct Implementation1 : boost::impl_ptr<Book>::implementation { Implementation1() : implementation(args) { ... } }; struct Implementation2 : boost::impl_ptr<Book>::implementation { Implementation2() : implementation(args) { ... } }; Book::Book(args) : impl_ptr_type(nullptr) { some_condition ? impl_ptr_type::emplace<Implementation1>(args) : impl_ptr_type::emplace<Implementation2>(args); }