Vous êtes sur la page 1sur 15

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

Vous aimerez peut-être aussi