I l@ve RuBoard Previous Section Next Section

1.8 Optional Functionality Through Incomplete Instantiation

It gets even better. C++ contributes to the power of policies by providing an interesting feature. If a member function of a class template is never used, it is not even instantiated—the compiler does not look at it at all, except perhaps for syntax checking.[5]

[5] According to the C++ standard, the degree of syntax checking for unused template functions is up to the implementation. The compiler does not do any semantic checking—for example, symbols are not looked up.

This gives the host class a chance to specify and use optional features of a policy class. For example, let's define a SwitchPrototype member function for WidgetManager.



// Library code


template <template <class> class CreationPolicy>


class WidgetManager : public CreationPolicy<Widget>


{


   ...


   void SwitchPrototype(Widget* pNewPrototype)


   {


      CreationPolicy<Widget>& myPolicy = *this;


      delete myPolicy.GetPrototype();


      myPolicy.SetPrototype(pNewPrototype);


   }


};


The resulting context is very interesting:

  • If the user instantiates WidgetManager with a Creator policy class that supports prototypes, she can use SwitchPrototype.

  • If the user instantiates WidgetManager with a Creator policy class that does not support prototypes and tries to use SwitchPrototype, a compile-time error occurs.

  • If the user instantiates WidgetManager with a Creator policy class that does not support prototypes and does not try to use SwitchPrototype, the program is valid.

This all means that WidgetManager can benefit from optional enriched interfaces but still work correctly with poorer interfaces—as long as you don't try to use certain member functions of WidgetManager.

The author of WidgetManager can define the Creator policy in the following manner:

Creator prescribes a class template of one type T that exposes a member function Create. Create should return a pointer to a new object of type T. Optionally, the implementation can define two additional member functions—T* GetPrototype() and SetPrototype(T*)—having the semantics of getting and setting a prototype object used for creation. In this case, WidgetManager exposes the SwitchPrototype (T* pNewPrototype) member function, which deletes the current prototype and sets it to the incoming argument.

In conjunction with policy classes, incomplete instantiation brings remarkable freedom to you as a library designer. You can implement lean host classes that are able to use additional features and degrade graciously, allowing for Spartan, minimal policies.

    I l@ve RuBoard Previous Section Next Section