PrevUpHomeNext

Construction and impl_ptr::null()

Тhe Pimpl base class (aliased as impl_ptr_type) is initialized with:

Book::Book(string const& title, string const& author)
:
   impl_ptr_type(in_place, title, author)
{}

In line with std::optional, std::variant and std::any the in_place argument is the disambiguation tag indicating that the underlying impl_ptr<Book>::implementation is constructed in-place with the remaining arguments. Consequently, a Book constructor with no matching impl_ptr<Book>::implementation constructor will fail to compile. Same goes for the default constructor:

Book::Book() : impl_ptr_type(in_place) {}

will try calling the default implementation() constructor and will fail to compile if there is no such.

To avoid potential ambiguity impl_ptr_type does not have the default constructor. To create a proxy with no implementation (if such is needed) initialize impl_ptr_type explicitly as:

Book::Book() : impl_ptr_type(nullptr)
{
   // A Book proxy object is created with no implementation.
}

or use boost::impl_ptr<Book>::null():

Book::Book() : impl_ptr_type(boost::impl_ptr<Book>null())
{
   // A Book proxy object is created with no implementation.
}

void
Book::do_something()
{
   if (!*this) // If no implementation, create one.
   {
       // Implementation is created later.
       impl_ptr_type::emplace(args);
   }
   ...
}

In the example the underlying impl_ptr_type and, consequently, Book are created "invalid" (like nullptr or an empty std::shared_ptr()). Later an impl_ptr_type<Book>::implementation instance is explicitly created using impl_ptr_type::emplace().

That nullptr-like concept is generalized via impl_ptr<Book>::null(). That is useful for lazy-instantiation optimization (as in the example above) or to support dynamic polymorphism (as discussed later) or to indicate a no-book condition:

Book
find_book()
{  ...
   return boost::impl_ptr<Book>::null(); // found nothing
}
...
if (Book book = find_book()) do something useful;
else                         report book-not-found;

It is probably worth mentioning that impl_ptr<Book>::null() is not part of Book public interface. It is up to the Book implementer to decide if such

Book::Book() : impl_ptr_type(nullptr) {}

"invalid" Book needs to be part of the public interface, if impl_ptr<Book>::null() is used internally, or if that functionality is used at all.


PrevUpHomeNext