Template Lab                
In this lab, we will look at some examples of Template Specialization.
The files are in ~cs253/Lab/Template.
Create a file called results.cc
, and turn it in for credit.
You must compile it with g++ -std=c++17 -Wall
,
and that must not produce any warnings or errors.
A video introduction is available.
                
A Bar Graph Template                
In 1.cc, we have a program that defines
the BarGraph
template. Here’s how to use it:
                
BarGraph<int> alpha;
alpha += 12;
alpha += 6;
alpha += 4;
alpha += 6;
alpha += 6;
alpha.dump();
This create a BarGraph
of int
s, uses it to count four
int
s, and then produce this bar graph:
                
4 *
6 ***
12 *
This template class has several features worth discussion:
                
- It uses a std::map to count the elements as they come in.
- The key of the map is the templated type
T
, an int, in
this case.
- The value of the map is an unsigned int. It’s unsigned
because it’s a counter, and counters can’t be negative. We may as
well use an unsigned int, which has no negative values,
but can hold twice as many positive values.
- The map is sorted by the key (an int, in this case). Therefore,
the output is in the order 4, 6, 12.
- It overloads
+=
to “add” items to the bar graph.
The return type of this operator+=
is void.
+=
usually returns a reference to *
this,
because all standard assignment operators do that,
but it’s only a convention, not a rule.
BarGraph
uses a std::string temporary to print a number of
stars. That is, string(23, '*')
calls the string ctor to
creates a temporary unnamed string that contains 23 asterisks.
- It uses an iterator to traverse (walk through) the sorted map.
Advantages of templates                
The benefit of a template is its generality. BarGraph
should work
for any type, as long as it is (think “Duck Typing”):
🦆
- copyable (copy ctor &
operator=
)
- comparable via
<
- printable via
<<
including int, float, string, etc.
                
Disadvantages of templates                
Sure, BarGraph
works for lots of types, but it’s not the most
efficient solution for all types. It uses a map, which is a general
solution, but that generality is not always needed. It’s like how a
chainsaw can cut through just about anything, but it’s not really
practical for eating dinner. Sometimes, a more specialized tool is
appropriate.
                
Consider 2.cc, which introduces template
specialization. It features a hand-written version BarGraph<bool>
.
This is a version of BarGraph
tuned specially for counting booleans.
Of course, the general version of BarGraph
still exists, so it works
for all other types, too.
                
The specialization BarGraph<bool>
is:
- Smaller: only has two unsigned variables.
- Faster: does a boolean test instead of a map lookup,
and doesn’t have to iterate through the possible values,
since there are only false and true.
- Better: outputs false and true instead of
0
and 1
.
Of course, it’s possible that g++’s implemention of map has a
specialization for map<bool,
whatever >
that is smaller & faster in just that way. Who knows?
                
Exercises                
- Copy 2.cc to
results.cc
, and use that from now on.
- Replace
.dump()
with an overloaded <<
so that you can insert a
BarGraph
object into an ostream.
- Do this for the templated
BarGraph
class, and all of its
template specializations. A template specialization should present
the same interface as the unspecialized class.
- Replace the uses of
.dump()
in main() with <<
.
- The
.dump()
method must no longer be present.
- Add a specialization for
BarGraph<char>
:
<<
must work for this specialization, also.
- It must use a fixed-size C array, or a std::array,
not a vector or a map.
- You may assume that the input will be only ASCII characters.
Unicode characters will fail horribly, but we’ll live with that
for this academic example.
- Do not simply store the incoming chars themselves.
Instead, store only counts. You want this to work even if
called with billions of items.
- You remember how
BarGraph<bool>
stored only two counts?
Why two? Because a bool has only two possible values.
How many counts do we need to store for an ASCII char?
- Add an operator so that you can do
delta += "foo"
for a
BarGraph<char>
. This should be equivalent to:
delta += 'f';
delta += 'o';
delta += 'o';
- Add a test case
delta += "Colorado";
to main()
for the operator you just implemented.
How to submit your work:                
In Canvas, check in the
file
results.cc
to the assignment “Lab11”.
It’s due 11:59ᴘᴍ MT Saturday, with a 24-hour late period for a 25% penalty.
                
How to receive negative points:                
Turn in someone else’s work.