Nicolai M. Josuttis: solutions in time  Ron's Member Idiom

Ron's Member Idiom (Base-From-Member Idiom)

When developing a class, sometimes a base class needs to be intialized with a member of the current class. A typical example is the implementation of user-defined stream buffers (see The C++ Standard Library, Section 13.13.3):
class fdoutbuf : public std::streambuf {
  public:
    explicit fdoutbuf(int fd);
    //...
};

class fdostream : public std::ostream {
  protected:
    fdoutbuf buf;
  public:
    explicit fdostream(int fd) : buf(fd), std::ostream(&buf) {
    }
    //...
};

This is undefined because C++'s initialization order mandates that the base class is initialized before the member it uses. Ron Klatchko and Dietmar Kühl developed a way around this by using the initialization order in his favor. Base classes are intialized in order of declaration, so moving the desired member to another base class, that is initialized before the desired base class, can ensure proper initialization. But note that virtual base classes are initialized before all other base classes. The solutions looks therefore as follows:

class fdoutbuf : public std::streambuf {
  public:
    explicit fdoutbuf(int fd);
    //...
};

class fdostream : protected virtual fdoutbuf, public std::ostream {
  public:
    explicit fdostream(int fd) : fdoutbuf(fd), std::ostream(&buf) {
    }
    //...
};

fdoutbuf has to be the first base class and virtual because std::ostream itself has a virtual base class (std::ios). As a result, the order of initialization is as follows:
- all virtual base classes in the order of declaration
- all non-virtual base classes in the order of declaration
- all members in the order of declaration

See http://lists.boost.org/MailArchives/boost/msg10147.php for an idea of a template that supports Ron's Member Idiom.

Thanks to Dietmar Kühl and Ron Klatchko for this trick and wording.

Home Page