What features make up the view concept? Figure 2 shows a feature diagram following Czarnecki and Eisenecker [5]. The most prominent feature is of course the container. Every view has an underlying container (that may actually be another view) holding the data elements on which the view operates.
The ownership semantics of the container are a point of variation. The view may just reference an external container and rely on the existence of the container during its lifetime, performing no resource management of any kind. Then the view may share the ownership of the underlying container with different views, copy constructed or assigned from each other. The container will be deleted together with the last referencing view. Changes in the underlying container will be visible through all the views that share the container. Finally, the view can own its underlying container exclusively, either by aggregation or by reference. In both cases, the container is copied when the view is copied, and changes in the underlying container are local to the view. Exclusive ownership by reference may be prefered if the container is constructed separately or the view needs to be exception-safe.
|
The functionality of the view is one more point of variation. Since views can be easily stacked to perform increasingly complex tasks, every single view can be restricted to one single task. There are filtering (showing only elements that satisfy a given predicate), transformation (showing the results of a transformation applied to the elements), and so on. Then there are views combining elements from two underlying containers, which then have a second container feature with the same subfeatures as above. Among them are the zip view (showing pairs of corresponding elements), union view (which concatenates two containers head to tail), and the crossproduct view (showing all possible pairs of elements).
Every view provides read access to its elements, but may or may not provide write access. Modification of the view's elements can be inhibited by the user defining a corresponding template parameter, but can also be restricted by functionality. E.g. for the transform view to be able to define element write access in a sensible way, the transformation must be invertible, whereas a crossproduct view cannot offer write access to individual elements at all. If the view is able to modify elements, it may or may not be able to modify the underlying container by inserting or erasing elements.
Finally, the iterator category of the view's iterators is a
feature that affects several algorithms working on the view. The
iterator category depends on the iterator category of the underlying
container(s), but can be restricted by the functionality. E.g. a
filtering view can have at most bidirectional iterators: Advancing an
iterator by an arbitrary amount
requires checking the predicate for
all the elements in between, and therefore is not more efficient than
increments.
In order to mimic STL containers as closely as possible and not to introduce unnecessary performance hits by this thin abstraction layer, all of the features are bound statically.
Currently, not all possible feature variations are implemented.