Today's lecture and studio focus on how function and class templates impose requirements on the types with which they are parameterized, and in doing so define sets of types that can be used to parameterize them. Those sets of types establish domains within which interface polymorphism can support the Liskov Substitution Principle, thus allowing types to be designed to work with particular templates by providing the necesary operations and member functions to allow that. Note that even non-template functions and classes may impose different requirements on the types they use, which we will explore at the beginning of this studio.
Please complete the following required exercises. I encourage you to please work in groups of 2 or 3 people on each studio (and the groups are allowed to change from studio to studio) though if you would prefer to complete any studio by yourself that is also allowed.
As you work through these exercises, please record your answers, and when
you finish them please log into Canvas, select this course in this semester, and
then upload a .txt
file containing your answers on the Canvas page
for this studio assignment. Only one submission per team, please, and if
you need to re-submit it the person who originally submitted the studio should
please be the one to do that.
Make sure that the name of each person who worked on these exercises is listed in the first answer, and make sure you number each of your responses in a manner that makes it easy to match your responses with each exercise.
First, ssh into shell.cec.wustl.edu
using your WUSTL
Key id and password and then use qlogin
to log into one
of the Linux Lab machines and then confirm that the version of g++
there is correct (as you did in Studio 0). Then
cd
into your directory for this course this semester, create a new
subdirectory for this studio, and cd
into it.
Copy the Makefile
from your previous studio into that
directory. As you work on this studio, please update the Makefile as needed so
that it will build an executable program called studio1
from the
files in that directory.
Add a header and source file to your directory, and in them declare and define a
struct that has a single (public) member variable of type int
, and a
(public) constructor that takes an int
and (in its base/member variable
initialization list) uses it to initialize the member variable.
Add a source file to your directory and in it define your program's main function
so that it constructs two objects of the struct type with different int
variables, prints out their member variables with a space in between them
to the standard output stream (cout
), and returns a
descriptively named symbol that has value 0 to indicate success.
Compile and run your program, and as the answer to this exercise please show (1) your code and (2) the ouput the program produced.
In your struct declaration, try adding =delete
declarations that
suppress the compiler's synthesis of the (1) copy constructor, (2) copy assignment
operator, and (3) destructor for the struct (please see LLM pp. 507 for examples
of the appropriate syntax to use for doing that). Try adding each of them one at
a time, try to build your program, and if it won't compile commenting out that
particular =delete
declaration so that you can see exactly which
of those the main function requires and which of them it doesn't.
As the answer to this exercise please show the lines of code that you added for this exercise, and for the lines that had to be commented out please explain briefly why it could not be compiled.
In your struct declaration, comment out any of the lines you added in the previous exercise that are not commented out already.
In your main function, after it prints out the objects' member variables, pass
the objects themselves (not their member variables) into a call to the
std::swap
function template and again print the objects' variables to
the standard output stream to show that their values have been reversed. Compile
and run your program and as the answer to this exercise please show the output
it produced (with the objects' values before and after the swap).
In your struct declaration, try uncommenting the =delete
declarations that suppress the compiler's synthesis of the (1) copy constructor,
(2) copy assignment operator, and (3) destructor for the struct. Again do this
one at a time, trying to build your program each time and if it won't compile
again commenting out that particular =delete
declaration so that
you can see exactly which of those is required and which of them isn't.
As the answer to this exercise please show all the =delete
declarations (including those that were commented out and those that were
not), and based on which if them had to be commented out (and which of them
did not need to be) please explain whether the std::swap
function template imposes additional requirements on the struct type (beyond
those imposed by the main function) and if so what those are.
Modify the declaration and definition of your struct so that it is a
struct template with a single parameterized type that defaults to int
and then modify your main function so that it declares its objects with
empty type parameter lists.
Modify the header and source files for your struct template so that the
header file includes the source file, and modify your Makefile
so that it treats the source file as a template source file and does not
try to compile it directly.
Compile and run your program, and ensure that it produces the same output as before. As the answer to this exercise please show your code with those modifications.
Modify the declaration and definition of your template so that it is a class instead of a struct, its member variable is private, and all of its member functions are public.
In the header and source file for the class template, declare and define
a template for a left shift operator (operator<<
) that takes
a reference to an
ostream
and a const reference to an object of the class type, inserts
the object's private member variable to the ostream
, and returns a
reference to the ostream
. Be sure to include the necessary library
header file and to add a using std::ostream;
statement.
In your class, declare that operator to be a friend of the class, so that it can access the object's private member variable (LLM pp. 665 has a good example of the kind of syntax you will need to use in order to do that).
Add any forward declarations of the class template or of the left shift operator that are needed (to the header file for your class template), so that your code will compile. Build and run your program and confirm that it produces the same output as before. As the answer to this exercise please show the code in the header file.
For this studio, please turn in the following:
Page posted Sunday October 23, 2022, and updated Tuesday October 25, 2022, by Chris Gill. Changes since original posting: