Templates
The Serialization package can stream objects of template classes and ordinary classes. It can also stream a template class that uses a base class pointer (polymorphism and templates). Although template classes don’t often inherit from a base class, this technique is useful for situations such as storing a mixed set of primitive types together in a collection.
Serialization support for templates requires use of special macro RW_DEFINE_STREAMABLE_TEMPLATE_POINTER() because the normal RW_DEFINE_STREAMABLE_POINTER() and RW_DEFINE_STREAMABLE_AS_SELF() macros don’t work with template classes. Calls to the RW_DEFINE_STREAMABLE_AS_BASE() macro must be placed in a source file for each type of pointer that will be used to stream an object of that template class.
The RW_DEFINE_STREAMABLE_TEMPLATE_POINTER() macro cannot be called with a template class directly; it must be called using typedefs for specific instantiations of the template. At present, only templates with a single parameter are supported, and the macro uses the name T for that parameter.
In the next example, a residential property has one or more pet_door objects parameterized by the type of pet: t_pet_door<class kind_of_pet>.
 
// examples\serial\template\pet_door.h
 
struct pet_door { // 1
RW_DECLARE_VIRTUAL_STREAM_FNS(pet_door)
 
public:
virtual ~pet_door() { }
};
 
template <typename T>
struct t_pet_door : public pet_door {
RW_DECLARE_VIRTUAL_STREAM_FNS(t_pet_door<T>) // 2
 
public:
 
virtual ~t_pet_door() { }
 
};
 
struct cat { }; // 3
struct monkey { };
 
// Allow object streaming of residential class
RW_DECLARE_STREAMABLE_AS_SELF(pet_door)
RW_DECLARE_STREAMABLE_POINTER(pet_door)
 
// Typedefs to allow streaming by reference
typedef t_pet_door<cat> cat_door; // 4
typedef t_pet_door<monkey> monkey_door;
 
RW_DECLARE_STREAMABLE_AS_SELF(cat_door)
RW_DECLARE_STREAMABLE_AS_BASE(cat_door, pet_door)
RW_DECLARE_STREAMABLE_POINTER(cat_door)
 
RW_DECLARE_STREAMABLE_AS_SELF(monkey_door)
RW_DECLARE_STREAMABLE_AS_BASE(monkey_door, pet_door)
RW_DECLARE_STREAMABLE_POINTER(monkey_door)
RW_DEFINE_STREAMABLE_TEMPLATE_POINTER(t_pet_door) // 5
 
template <class T> // 6
RW_BEGIN_STREAM_CONTENTS(t_pet_door<T>)
{
RW_STREAM_PARENT(pet_door)
}
RW_END_STREAM_CONTENTS
 
//1 Base class for collecting the template specializations.
//2 Declare the stream contents function for the template.
//3 cat and monkey structs used to specialize the t_pet_door template.
//4 These typedefs are needed for each specialization of the t_pet_door template. These could reside in pet_door.cpp also.
//5 The RW_DEFINE_STREAMABLE_TEMPLATE_POINTER macro. (Note that, because this is a template class, the DEFINE macro goes into the header file rather than the source file.)
//6 The template version of a streamContents() function. Note its presence in the header file, rather than in the source file.
The following source code for pet_door is from: examples\serial\template\pet_door.cpp.
 
RW_BEGIN_STREAM_CONTENTS(pet_door) // 1
RW_END_STREAM_CONTENTS
 
// Allow object streaming of pet_door class
RW_DEFINE_STREAMABLE_AS_SELF(pet_door)
RW_DEFINE_STREAMABLE_POINTER(pet_door)
 
// Allow template specialization streaming by reference
RW_DEFINE_STREAMABLE_AS_SELF(cat_door) // 2
RW_DEFINE_STREAMABLE_AS_BASE(cat_door,pet_door)
RW_DEFINE_STREAMABLE_POINTER(cat_door)
 
RW_DEFINE_STREAMABLE_AS_SELF(monkey_door)
RW_DEFINE_STREAMABLE_AS_BASE(monkey_door,pet_door)
RW_DEFINE_STREAMABLE_POINTER(monkey_door)
 
//1 The streamContents() function for the non-template base class is written in the usual way and put in the usual place.
//2 Typedefs from pet_door.h support serialization by referencing the template instantiations.