ZStreamXXclasses are just interfaces. They make it easy to wrap a standard lightweight API around arbitrary data sources, sinks and filters, and pass them to library and application code. They deliberately do not address lifetime issues. The various
ZStreamerXXclasses together define a standard mechanism for encapsulating real streams inside refcounted containers, making it possible to manage the lifetime of a stream in a safe fashion.
The defining aspects of a
ZStreamerXX are the fact that it is refcounted, and has the
GetStreamXX virtual methods a concrete instance is required to implement. Although there's no physical protection against it, it's a requirement that when a
ZStreamXX reference is returned that reference must remain valid for the lifetime of the
ZStreamerXX that returned it.
Many of the standard
ZStreamXX classes have matching
ZStreamerXX classes, but this is not mandatory for each
ZStreamXX derivative that you define. If you do it will make it possible for that stream to particpate in streamer operations. To make it a little easier to wrap arbitrary streams inside a streamer there are template definitions. For
ZStreamerX the templates are called
ZStreamerX_T takes a template parameter which is your stream's class name, and has two constructors. One takes no parameters, the other takes a single parameter which is passed on to your stream's constructor.
ZStreamerX_FT is the template for a filter stream. Its default constructor is protected and thus inaccessible to code, because a filter stream makes no sense without a sink/source stream. Of the two accessible constructors one takes a
ZRef<ZStreamerXX> and a single parameter, the other takes only a
ZRef<ZStreamerXX>. Your filter stream will be constructed with either the parameter and the result of
ZStreamerXX::GetStreamXX, or with just the result of
You can see that if you want a
ZStreamXX that can be wrapped in a
ZStreamerXX_T or a
ZStreamerXX_FT, and your stream requires parameters to initialize it then it must have a constructor that takes a single parameter, or a single parameter and a sink/source stream. Although you can use
pair<Type1, Type2> or define a struct to carry the initialization payload if you need more than a single parameter, it can often be easier to manually write a
ZStreamerXX classes have a hierarchy that parallels the
ZStreamerR +--ZStreamerU +----ZStreamerRPos +------ZStreamerRWPos +--ZStreamerRW ZStreamerW +--ZStreamerWPos +----ZStreamerRWPos +--ZStreamerRW
You'll notice that ZStreamerRWPos multiply inherits from both ZStreamerRPos and ZStreamerWPos, and ZStreamerRW from both ZStreamerR and ZStreamerW. As ZStreamerR and ZStreamerW each descend from ZRefCounted, and we require a single ZRefCounted subobject in any ZRefCounted descendant, ZStreamerR and ZStreamerW have ZRefCounted as a virtual base class. The first and only time in 17 years of C++ programming where I've needed to do this.