This Week C++ Templates
Another form of polymorphism (interface based) Let you plug different types into reusable code
CSE 332: C++ templates
Overview of C++ Templates
Templates are used to plug in different types
Can re-use same code with int, string, etc.
Also called type parameterization
Types are given as parameters to a template Like variables are given as a functions parameters
Can make templates for functions and classes
The user of a class template must declare the type parameters when declaring an instance Dont have to declare the type parameters when calling a function template (call as though a non-template function)
The compiler figures it out for you, based on function call signature
CSE 332: C++ templates
Files for C++ Templates
Keep declarations and definitions separate
Just as you would for non-template classes and functions Have separate header (declarations) and source (definitions) files
Separate template and non-template code
For example, if a template relates to a class, put template in header and source files with similar (but different) names
array.h array.cc array_T.h array_T.cc
Some compilers (like g++) require that template definitions be included with their declarations
// . . . at the end of array_T.h #if defined (TEMPLATES_REQUIRE_SOURCE) #include "array_T.cc" #endif /* TEMPLATES_REQUIRE_SOURCE */ #endif /* ARRAY_T_H */
CSE 332: C++ templates
Introduction to Function Templates
template <typename T> void swap(T &lhs, T &rhs) { T temp = lhs; lhs = rhs; rhs = temp; } int main () { int i = 3; int j = 7; swap (i,j); return 0; }
Basic idea
same code is re-used for different types
Function template swap
takes one type parameter, T
Definition interchanges values of two passed arguments
of the parameterized type
Compiler infers type is really int when swap is called Compiler instantiates the function template definition using type int
CSE 332: C++ templates
Introduction to Class Templates
template <typename T> class Array { public: Array(const int size); ~Array(); private: T * values_; const int size_; };
int main() { Array<int> a(10); Array<string> b(5); return 0; }
Parameterized type T must be specified in class template declaration
Both as a parameter, and where its used in the class
When an instance is declared, must also explicitly specify the concrete type parameter
E.g., int vs. string in function main() In previous function template example, didnt have to say swap<int>
CSE 332: C++ templates
Tips on Using Function and Class Templates
Push common code and variables up into nontemplate base classes
Gives compiler less work to do instantiating templates Reduces program size and compilation time
Use function templates when you want type parameterization to be invisible to programmer
To force an explicit declaration of the parameterized type, use member functions of class templates instead
Use class templates when you want to parameterize member variables types
Lots of containers in the STL do this (vector, list, etc.) Well talk about the STL and how it uses templates later in the semester
CSE 332: C++ templates
Templates Have a Different View of Types
template <typename T> void swap(T &lhs, T &rhs) { T temp = lhs; lhs = rhs; rhs = temp; } int main () { int i = 3; int j = 7;
swap (i,j); return 0; }
Look at what swap requires of its parameterized types
Copy construction T temp = lhs; Assignment lhs = rhs; rhs = temp;
These requirements are called a templates concept A type that meets those requirements is called a model of that concept Can substitute any type that models a templates concept
CSE 332: C++ templates
Inheritance vs. Concept Refinement
Class1 Concept1
inherits from
T1
T2
T1
T2
refines
Class2
is an instance of models
Concept2 T3 T4
T3
T4
Explicit inheritance relation between classes
Class2 advertises its parent, Class1
Implicit refinement relation between concepts
Concept2 adds to the requirements of Concept1
CSE 332: C++ templates
Inheritance vs. Concept Refinement, part II Similarities
Both define a type hierarchy (a partial order)
Reflexive and transitive, but not symmetric Can be expressed as a directed acyclic graph Can be used by a compiler to do type checking
Both support type substitution, polymorphism
Differences
Again, refinement is implicit, inheritance is explicit
Programmer must define all inheritance relationships C++ compiler infers concept/models relationships for us
Type substitution and polymorphism mechanisms
CSE 332: C++ templates
OO vs. Generic Programming Paradigms
Liskov Substitution Principle
If S is a subtype of type T (S meets all the requirements of T), then whenever we need an instance of T we can substitute an instance of S.
Object-Oriented (OO) Programming: Public Inheritance
class Derived: public Base { }; void foo (Base &b); Derived d; foo (d);
Generic Programming: Concepts, Models, Refinement
Class A only supports default construction Class B supports assignment and copy construction as well as all other operators A support Can use B in any template whose concept A models Cannot use A in any template whose concept B models
CSE 332: C++ templates
Extending Interfaces
Substitution is often non-symmetric
S replaces T, but not vice versa Often due to S extending the interface T provides
In OO Programming: Public Inheritance
class Base {public: void baz ();}; // Base only has baz class Derived: public Base {public: void bar ();}; // S adds bar
In Generic Programming: Concept Refinement
An STL random access iterator provides +=, -=, and ++
For example, an iterator using a pointer into an array
An STL forward iterator provides ++ but some forward iterators may not provide += or -=
For example an iterator using a pointer into a linked list
CSE 332: C++ templates
Polymorphism with Templates Substitution may provide different behaviors
Poly = many + Morph = form When we can substitute types, we want to get specialized behaviors when using different types
In OO programming
Derived classes can override base class behaviors Using virtual functions, we get polymorphism
Can we do something similar with Concepts and types that model them in templates?
I.e., so we get customized behavior for specific (more refined) templates?
CSE 332: C++ templates
Specializing Behaviors of Types
What mechanisms are available in C++?
With OO programming
We combine public inheritance & virtual methods:
class Base {public: virtual void foo () {cout << Base;} }; class Derived : public Base {virtual void foo () {cout << Derived;}};
With Generic programming
We combine operator/function overloading with template specialization mechanisms Sometimes called interface polymorphism
CSE 332: C++ templates
Template Specialization Allows us to override behaviors
Of function templates or class templates
Can override default (base) behavior:
template <typename T> print (T t) {cout << t << endl;} template <> print <char *> (char * str) {cout << (void *) str << endl;}
Partial specialization possible (some compilers)
Leave types of some parameters unspecified While specializing on explicit types for others E.g., on a null_guard type to remove acquire and release overhead if no dynamic allocation is done
CSE 332: C++ templates
Review Questions
How are inheritance-based (OO) and interfacebased (generic) substitution similar, and how do they differ? What are the similarities and differences between type polymorphism with inheritance (OO) and with concepts (generic)? How does C++ template specialization work? How do you declare/define a generic template, and different specializations of it?
CSE 332: C++ templates