mirror of
https://gitlab.com/fbb-git/cppannotations
synced 2024-11-16 07:48:44 +01:00
d84a4013af
git-svn-id: https://cppannotations.svn.sourceforge.net/svnroot/cppannotations/trunk@485 f6dd340e-d3f9-0310-b409-bdd246841980
137 lines
7.8 KiB
Text
137 lines
7.8 KiB
Text
An ordinary class may be used as the base class for deriving a template
|
|
hi(class template: derived from ordinary class) class. The advantage
|
|
of such an inheritance tree is that the base class's members may all be
|
|
compiled beforehand. When objects of the class template are now instantiated
|
|
only the actually used members of the derived class template must be
|
|
instantiated.
|
|
|
|
This approach may be used for all class templates having member functions
|
|
whose implementations do not depend on template parameters. These members may
|
|
be defined in a separate class which is then used as a base class of the
|
|
class template derived from it.
|
|
|
|
As an illustration of this approach we'll develop such a class template
|
|
below. We'll develop a class tt(Table) derived from an ordinary class
|
|
tt(TableType). The class tt(Table) displays elements of some type in a
|
|
table having a configurable number of columns. The elements are either
|
|
displayed horizontally (the first em(k) elements occupy the first row) or
|
|
vertically (the first em(r) elements occupy a first column).
|
|
|
|
When displaying the table's elements they are inserted into a stream. The
|
|
table is handled by a separate class (tt(TableType)), implementing the table's
|
|
presentation. Since the table's elements are inserted into a stream, the
|
|
conversion to text (or tt(string)) is implemented in tt(Table), but the
|
|
handling of the strings themselves is left to tt(TableType). We'll cover some
|
|
characteristics of tt(TableType) shortly, concentrating on tt(Table)'s
|
|
interface first:
|
|
itemization(
|
|
it() The class tt(Table) is a class template, requiring only one template
|
|
type parameter: tt(Iterator) referring to an iterator to some data type:
|
|
verbinsert(HEAD)(examples/table/table/table.h)
|
|
it() tt(Table) doesn't need any data members. All data manipulations are
|
|
performed by tt(TableType).
|
|
it() tt(Table) has two constructors. The constructor's first two
|
|
parameters are tt(Iterator)s used to iterate over the elements that must be
|
|
entered into the table. The constructors require us to specify
|
|
the number of columns we would like our table to have as well as a
|
|
em(FillDirection). tt(FillDirection) is an tt(enum),
|
|
defined by tt(TableType), having values tt(HORIZONTAL) and tt(VERTICAL). To
|
|
allow tt(Table)'s users to exercise control over headers, footers, captions,
|
|
horizontal and vertical separators, one constructor has tt(TableSupport)
|
|
reference parameter. The class tt(TableSupport) will be developed later as a
|
|
virtual class allowing clients to exercise this control. Here are the class's
|
|
constructors:
|
|
verbinsert(CONS)(examples/table/table/table.h)
|
|
it() The constructors are tt(Table)'s only two public members. Both
|
|
constructors use a base class initializer to initialize their tt(TableType)
|
|
base class and then call the class's private member tt(fill) to insert data
|
|
into the tt(TableType) base class object. Here are the constructor's
|
|
implementations:
|
|
verbinsert(CONSIMP)(examples/table/table/table.h)
|
|
it() The class's tt(fill) member iterates over the range of elements
|
|
rangett(begin, end), as defined by the constructor's first two parameters.
|
|
As we will see shortly, tt(TableType) defines a protected data member
|
|
tt(std::vector<std::string> d_string). One of the requirements of the data
|
|
type to which the iterators point is that this data type can be inserted into
|
|
streams. So, tt(fill) uses a tt(ostringstream) object to obtain the textual
|
|
representation of the data, which is then appended to tt(d_string):
|
|
verbinsert(FILL)(examples/table/table/table.h)
|
|
)
|
|
|
|
This completes the implementation of the class tt(Table). Note that this
|
|
class template only has three members, two of them constructors. Therefore, in
|
|
most cases only two function templates will have to be instantiated: a
|
|
constructor and the class's tt(fill) member. For example, the following
|
|
defines a table having four columns, vertically filled by tt(string)s
|
|
extracted from the standard input stream:
|
|
verb(
|
|
Table<istream_iterator<string> >
|
|
table(istream_iterator<string>(cin), istream_iterator<string>(),
|
|
4, TableType::Vertical);
|
|
)
|
|
The fill-direction is specified as
|
|
tt(TableType::VERTICAL). It could also have been specified using tt(Table),
|
|
but since tt(Table) is a class template its specification would have been
|
|
slightly more complex: tt(Table<istream_iterator<string> >::VERTICAL).
|
|
|
|
Now that the tt(Table) derived class has been designed, let's turn our
|
|
attention to the class tt(TableType). Here are its essential characteristics:
|
|
itemization(
|
|
it() It is a ordinary class, designed to operate as tt(Table)'s base
|
|
class.
|
|
it() It uses various private data members, among which tt(d_colWidth), a
|
|
vector storing the width of the widest element per column and tt(d_indexFun),
|
|
pointing to the class's member function returning the element in
|
|
tt(table[row][column]), conditional to the table's fill
|
|
direction. tt(TableType) also uses a tt(TableSupport) pointer and a
|
|
reference. The constructor not requiring a tt(TableSupport) object uses the
|
|
tt(TableSupport *) to allocate a (default) tt(TableSupport) object and then
|
|
uses the tt(TableSupport &) as the object's alias. The other constructor
|
|
initializes the pointer to 0 and uses the reference data member to refer to
|
|
the tt(TableSupport) object provided by its parameter. Alternatively, a static
|
|
tt(TableSupport) object could have been used to initialize the reference data
|
|
member in the former constructor. The remaining private data members are
|
|
probably self-explanatory:
|
|
verbinsert(DATA)(examples/table/tabletype/tabletype.h)
|
|
it() The actual tt(string) objects populating the table are stored in a
|
|
protected data member:
|
|
verbinsert(PROT)(examples/table/tabletype/tabletype.h)
|
|
it() The (protected) constructors perform basic tasks: they initialize the
|
|
object's data members. Here is the constructor expecting a reference to a
|
|
tt(TableSupport) object:
|
|
verbinclude(examples/table/tabletype/tabletype.cc)
|
|
it() Once tt(d_string) has been filled, the table is initialized by
|
|
tt(Table::fill). The tt(init) protected member resizes tt(d_string) so
|
|
that its size is exactly tt(rows x columns), and it determines the maximum
|
|
width of the elements per column. Its implementation is straightforward:
|
|
verbinclude(examples/table/tabletype/init.cc)
|
|
it() The public member tt(insert) is used by the insertion operator
|
|
(oplshift()) to insert a tt(Table) into a stream. First it informs the
|
|
tt(TableSupport) object about the table's dimensions. Next it displays the
|
|
table, allowing the tt(TableSupport) object to write headers, footers and
|
|
separators:
|
|
verbinclude(examples/table/tabletype/insert.cc)
|
|
it() The tt(cplusplus.yo.zip) archive contains tt(TableSupport)'s full
|
|
implementation. This implementation is found in the directory
|
|
tt(yo/classtemplates/examples/table). Most of its remaining members are
|
|
private. Among those, these two members return table element
|
|
tt([row][column]) for, respectively, a horizontally filled table and a
|
|
vertically filled table:
|
|
verbinsert(INDEX)(examples/table/tabletype/tabletype.h)
|
|
)
|
|
|
|
The support class tt(TableSupport) is used to display headers, footers,
|
|
captions and separators. It has four virtual members to perform those tasks
|
|
(and, of course, a virtual constructor):
|
|
itemization(
|
|
itt(hline(size_t rowIndex)): called just before the elements in row
|
|
tt(rowIndex) will be displayed.
|
|
itt(hline()): called immediately after displaying the final row.
|
|
itt(vline(size_t colIndex)): called just before the element in column
|
|
tt(colIndex) will be displayed.
|
|
itt(vline()): called immediately after displaying all elements in a row.
|
|
)
|
|
The reader is referrred to the tt(cplusplus.yo.zip) archive for the full
|
|
implementation of the classes tt(Table), tt(TableType) and tt(TableSupport).
|
|
Here is a little program showing their use:
|
|
verbinclude(examples/table/table.cc)
|