Models
Concepts describe a set of requirements, which are satisfied by a
family of abstractions. The abstractions are typically data types or
sets of data types, which we call models. For instance, a
pointer is a model of the Iterator concept;
alternatively, we can say that a pointer models
the Iterator concept.
One of the most important aspects of Generic Programming is that
the set of models for a given concept is neither known nor fixed. A
given concept is written using a small, known set of models--say,
nodes in a linked list and pointers into arrays--but will apply to
many, many other data types, such as an pre-order iteration through
a binary tree. It is precisely this openness that makes Generic
Programming suitable for the design of reusable libraries, because a
generic algorithm works equally well with any models of the
concepts it requires, whether the algorithm author considered those
data types or not. When we developed the sum() algorithm
earlier in this introduction, did we realize that it could apply to
integers read in from a file, or over a network, or even values
generated by repeated calling a random number generator? Any of the
data types that perform these operations can be models of
the Iterator concept, and therefore will work with
our generic sum() algorithm.
Similarly, when a data type is created we do not need to know all
of the concepts that it will model. If at some point we find that we
need our type to model a new concept, we can implement the required
syntax without changing our data type. This ability,
called retroactive modeling, allows anyone to adapt existing
data types for use in generic algorithms. For instance, look back at
how we have added
the iterator operations
and associated types for
pointers: we did not have to modify the definition of pointers at
all, nor could we have because they are built-in types. By making
all of our requirements external to the data types, we allow
retroactive modeling and avoid forcing changes to existing data
types.
|