Sunday, April 29, 2007

Boost C++ Idioms

This time lets take a brief look at some nifty C++ idioms in the Boost peer-reviewed libraries. We will talk about Boost Base-from-Member idiom, Boost Safe bool idiom, Boost Named External Argument idiom, Boost Non-member get() idiom, Boost Meta-function wrapper idiom, Boost Iterator pair idiom, and the Boost Mutant idiom.

  • Boost Base-from-Member idiom

  • This idiom is used to initialize a base class from a data-member of the derived class. It sounds contradictory to the rules of C++ language and that is the reason why this idiom is present. It basically boils down to pushing the parameter data member in a private base class and put that private base class before the dependent base class in the derivation order. A generalization of the technique can be found here.

  • Boost Safe bool idiom

  • Many authors have talked about the evils of type conversion functions defined in a class. Such functions allow the objects of that type to participate in nonsensical expressions. One good example is in standard C++:

    std::cout << std::cin << std::cerr; // Compiles just fine!

    The safe bool idiom invented by Peter Dimov eliminates these problems. It is used in std::auto_ptr, boost::shared_ptr. Bjorn Karlsson, the author of the book Beyond the C++ Standard Library, tell us about this nifty technique called the safe bool idiom in his article on Artima.

  • Boost Named External Argument idiom

  • It is a technique to pass parameters to included header files! Quickest way to learn about this idiom is to read this one paragraph.

  • Boost Non-member get() idiom

  • In Cheshire Cat idiom or pimpl like idioms, accessing non-const functions of the pointee wrapped inside a const wrapper object is a problem. I discussed a technique to have const-overloaded arrow operator to avoid such an accident. This is important because the user of the wrapper does not (and should not) know that it is in-fact using pimpl idiom. The Boost non-member get() idiom deals with the same problem, albeit differently, in the context of value_initialized objects. It also used const-overloaded versions of get() functions.

  • Boost Meta-function wrapper idiom

  • The compilers that don't support template template parameters, meta-function wrapper (a.k.a. Policy Clone idiom) is useful to instantiate a clone of template parameter. Essentially, it says, "I don't know what type you are, and I don't know how you were parameterized, but I want an exact clone of you, which is parameterized with type T (T is known)."
    Note that it is one rare place where we have to use both the keywords typename and template in the typedef. For compilers that support template template parameters, there is no need to use this idiom. Arguably this idiom is more general than template template parameters.

    Not much information other than simple googling is available about the remaining two idioms: Boost Iterator pair idiom and Boost Mutant idiom. Any inputs are more than welcome!

    Tuesday, April 24, 2007

    new, delete, custom memory allocation, and exception safety

    This post will hopefully push you ahead to a higher level of expertise in memory management mechanics of C++ and exception safety. Here we go...

    Some warm-up:

    Consider a function
    void func (T*, U*);
    int main() {
    func (new T, new U); // line 1
    Calling the function like in line 1 is a bad idea because parameter evaluation sequence is not standard and therefore it memory allocation of second new (it could T or U) fails, we have a blatant memory leak.

    What to do? Lets use our silver bullet: auto_ptr! but it fails too for the same reasons. Consider a function
    void func (std::auto_ptr <T>, std::auto_ptr <U>);

    Now it is possible that, even before any auto_ptrs are constructed, new may throw or a constructor may throw and all efforts go in vain. Details can be found in Hurb Sutter's More Excetional C++: Item 20-21.

    So we should separate the allocation and the function call.
    auto_ptr <T> t1 = new T; auto_ptr <U> u1 = new U;
    func (t1, u1);

    That's no better either!

    Now if func throws some exception X, there is no way to retrieve the objects pointed by t1 and u1 because by the time control flow reaches a catch block, the two pass-by-value auto_ptr parameters deleted the free store already! Never pass auto_ptrs by value if a function can throw. BTW, returning auto_ptrs by value is a good idea for factory and clone like functions.

    Enough of warm-up. Lets do some real cardiac exercise!

    Note: If the constructor of a dynamically allocated object throws an exception then C++ reclaims the allocated memory automatically by invoking delete automatically. It is a very good thing.

    If you have one or more overloaded new operators in your class, you should have overloaded delete operator having exactly matching signature. Exactly matching signature part is important because if the constructor that is called after successful completion of your overloaded new throws then C++ automatically invokes the corresponding overloaded delete operator that has exactly the same signature to reclaim the memory. I have given declarations of some possible overloaded new and their corresponding delete couterparts.

    #include <new>
    struct X {};

    class C {
    static void * operator new (size_t size); // typical overloaded new
    static void operator delete (void *p, size_t size);
    // A matter of style: declaration of size can be removed
    // from the destructor above!

    static void * operator new (size_t size, const X &x);
    static void operator delete (void *p, const X &x);

    static void * operator new (size_t size, std::nothrow_t) throw ();
    static void operator delete (void *p, std::nothrow_t) throw ();

    static void * operator new (size_t size, void *p); // placement new
    static void operator delete (void *p, void *);
    // In the above overloaded delete, signature appears redundant
    // but it is necessary! Both pointer values are the same!

    static void * operator new [] (size_t size); // Array new
    static void operator delete [] (void *p); // Array delete

    static void * operator new [] (size_t size, const X &x);
    static void operator delete [] (void *p, const X &x);

    int main (void)
    C *c = new (std::nothrow) C;
    // Here, if the constructor of C throws then the nothrow
    // overloaded delete will be called automatically.
    c->~C(); // Explicit destructor invocation because delete c does not help.
    C::operator delete (c, std::nothrow); // Free up the memory.
    This post was motivated by Herb Sutter's Exceptional C++: Item 36.

    Wednesday, April 11, 2007

    Non-Virtual Interface (NVI) idiom and the design intent

    Assuming that the philosophy of Non-Virtual Interface (NVI) idiom is strictly adhered I came up with a table that summarizes the design intent in terms of access modifiers and virtuality. Strict adherence of NVI allows separation of the interface of a class into two distinct interfaces: client interface (public non-virtual) and subclass interface (protected virtual/non-virtual). Such a structure helps mitigate the Fragile Base Class (FBC) Interface problem if discipline is followed. Its only downside is a little bit of code bloat. More about this approach of resolving FBC can be found here.

      non-virtual virtual but not pure pure virtual without body pure virtual with body
    Public Clients expect substitutability. Extension points are
    encapsulated.  Subclasses should stay away from this if an equivalent
    protected function using NVI is given.
    Clients expect substitutability. Extension points are
    visible. Subclasses can optionally extend  them but assuming NVI is
    place, subclasses should not reuse it.
    Substitutability is mandatory as base class itself can't be
    Substitutability is mandatory as base class itself can't be
    instantiated. Subclasses should call the method in the base. e.g.,
    Protected For the purpose of reuse only by subclasses. An interface
    for subclasses. Beware of the Fragile Base Class (FBC) interface problem.
    An optional extension point for subclasses. FBC applies
    A mandatory extension point for subclasses A mandatory extension point for subclasses and it should
    call the method in the base. e.g., destructor.
    Private Clients as well as subclasses have to live with it. Like
    final keyword in Java. Not for reuse. Top secret
    of a class.
    If you happen to know the secret, it is not for (re)use but
    you can risk extending it. Don't scream if the the treasure evaporates
    If you happen to know the secret, it is not for (re)use but
    you must risk extending it! Surprises for tomorrow if base is updated.
    Ditto as for pure virtual without body

    The structure of NVI is similar to the Thread-safe Interface pattern. The purpose of public methods in thread-safe interface is to acquire lock and let the helper functions do the real job without worrying about locking. In NVI, the public non-virtual methods do a simple job of dynamic dispatching of protected virtual helper functions.

    Tuesday, April 10, 2007

    Virtuality is an implementation detail !

    There are many ways of achieving separation of interface from implementation:

    1. Using Interface Definition Language (IDL) as in CORBA
    2. Bridge Pattern (GoF)
    3. Pimpl idiom
    4. Handle/Body idiom
    5. Envelope/Letter idiom
    6. Template Method pattern (GoF)

    The Template Method way of achieving this is a bit tricky. It basically boils down to a few class design guidelines based on access modifiers, virtuality and language expressibility. It is also known as Non-Virtual Interface (NVI) idiom.

    1. Prefer to make interfaces non-virtual, using Template Method.
    2. Prefer to make virtual functions private.
    3. Only if derived classes need to invoke the base implementation of a virtual function, make the virtual function protected.
    4. A base class destructor should be either public and virtual, or protected and non-virtual.

    For more information please see: Virtuality and Virtually Yours.
    A few more elemental base class idioms can be found here.
    A comparison of the above approaches can be found in this ACCU article.

    Thinking of it more, the Template Method used in this way can be thought of as a special case of Bridge, where the pointer to implementation is implicitely replaced by this pointer.