CSE 332: C++ template examples Concepts and Models Templates impose requirements on type parameters...

11
CSE 332: C++ template examples Concepts and Models Templates impose requirements on type parameters Types that are plugged in must meet those requirements Otherwise, the code won’t compile (and errors will say why) • The set of requirements imposed is called a concept Any specific type that meets the requirements is a model of that concept What requirement(s) does the expression return first; impose? What about while(first != last && *first != value) { ++first; } const T & Iterator

Transcript of CSE 332: C++ template examples Concepts and Models Templates impose requirements on type parameters...

Page 1: CSE 332: C++ template examples Concepts and Models Templates impose requirements on type parameters –Types that are plugged in must meet those requirements.

CSE 332: C++ template examples

Concepts and Models• Templates impose requirements on type parameters

– Types that are plugged in must meet those requirements– Otherwise, the code won’t compile (and errors will say why)

• The set of requirements imposed is called a concept• Any specific type that meets the requirements is a

model of that concept• What requirement(s) does the expression return first; impose?

• What about while(first != last && *first != value) {

++first;

} const T &

Iterator

Page 2: CSE 332: C++ template examples Concepts and Models Templates impose requirements on type parameters –Types that are plugged in must meet those requirements.

CSE 332: C++ template examples

Interface Polymorphism: Concept Refinement

• A concept C is a refinement of concept D if C imposes all of the requirements of D

• Modeling and refinement satisfy three formal properties– Reflexivity: A concept refines

itself– Containment: if T models C and

C refines D then T models D– Transitivity: If C refines D then

C refines any concept D refines

• What in the OO paradigm is this like? How does it differ?

C1

C2

T1 T2

T3 T4

C0

containment

transitivity

can substitute, e.g., T3 for T1

Page 3: CSE 332: C++ template examples Concepts and Models Templates impose requirements on type parameters –Types that are plugged in must meet those requirements.

CSE 332: C++ template examples

One Last Detail: Associated Typestemplate <typename T>class Array :

public ArrayBase {public: typedef T* iterator; Array(const int size); ~Array(); iterator begin () { return m_values;} iterator end () { return m_values+m_size;}private: T * m_values;};

void foo { Array<int> a; fill_array(a); for (Array<int>::iterator i =

a.begin(); i != a.end(); ++i) { cout << *i << “ ” << endl; }}

• A type parameter is not concrete until its instantiated

• The compiler can work around that in many cases

• But sometimes the compiler needs more information

• Additional information can be associated with a type– For example, a class template

can define an iterator type– Available to the template and

code that uses the template– More about how this is done

(and why) in later lectures

Page 4: CSE 332: C++ template examples Concepts and Models Templates impose requirements on type parameters –Types that are plugged in must meet those requirements.

CSE 332: C++ template examples

C++ Templates and Interface Polymorphism

• Two examples– Function template for printing different types– Class template for a linked list

• First example will refine a program several times– Ending up with a specialized reusable function template– Shows how to write general and specialized templates

• Second example will walk through finished code– Look at how to declare and define a class template– Look at another data structure that uses dynamic memory– A few practicalities you may need to know about

• E.g., including template source, working around compiler issues

Page 5: CSE 332: C++ template examples Concepts and Models Templates impose requirements on type parameters –Types that are plugged in must meet those requirements.

CSE 332: C++ template examples

First Example: Printing Different Types #include <iostream>

using namespace std;

int main (int, char *[]) {

int i = 7;

bool b = false;

int * ip = &i;

char * cp = "hello, world!";

void * vp = cp;

cout << "i is " << i << endl;

cout << "b is " << b << endl;

cout << "ip is " << ip << endl;

cout << "cp is " << cp << endl;

cout << "vp is " << vp << endl;

return 0;

}

• Large number of types in C++• Each handled a bit differently• For example, << with ostream• Simply giving to cout gives

i is 7

b is 0

ip is 0xfef69094

cp is hello, world!

vp is 0x8048a3c

• Let’s make some improvements

Page 6: CSE 332: C++ template examples Concepts and Models Templates impose requirements on type parameters –Types that are plugged in must meet those requirements.

CSE 332: C++ template examples

Improve the Output for bool #include <iostream>

using namespace std;

int main (int, char *[]) {

. . .

cout << "i is " << i << endl;

cout << "b is " << boolalpha

<< b << endl;

cout << "ip is " << ip << endl;

cout << "cp is " << cp << endl;

cout << "vp is " << vp << endl;

return 0;

}

• First, fix how bool is output• Use an iostream manipulator

std::boolalpha– prints true or false– Instead of 1 or 0

• Now we geti is 7

b is false

ip is 0xfef2aa04

cp is hello, world!

vp is 0x8048b0c

• But what about the pointers?

Page 7: CSE 332: C++ template examples Concepts and Models Templates impose requirements on type parameters –Types that are plugged in must meet those requirements.

CSE 332: C++ template examples

Improve the Output for Pointers#include <iostream>

using namespace std;

int main (int, char *[]) {

. . .

cout << "i is " << i << endl;

cout << "b is " << boolalpha

<< b << endl;

cout << "ip is " << ip <<

" (points to " << *ip

<< ")" << endl;

cout << "cp is " << reinterpret_cast<void *> (cp)

<< " (points to \"" << cp

<< "\")" << endl;

cout << "vp is " << vp << endl;

return 0;

}

• Now, fix pointers• Use reinterpret_cast

– Convert char * to void *

• Use dereferencing– Convert int * to int

• Now we have what we want i is 7

b is false

ip is 0xfef23584 (points to 7)

cp is 0x8048b70 (points to "hello, world!")

vp is 0x8048b70

• But, don’t want to have to do all that over again– Next time we want to print

Page 8: CSE 332: C++ template examples Concepts and Models Templates impose requirements on type parameters –Types that are plugged in must meet those requirements.

CSE 332: C++ template examples

Refactor the Code with a Function Template#include <iostream>

using namespace std;

#include "common_T.h"

int main (int, char *[]) {

int i = 7;

bool b = false;

int * ip = &i;

char * cp = "hello, world!";

void * vp = cp;

print(cout, "i is ", i);

print(cout, "b is ", b);

print(cout, "ip is ", ip);

print(cout, "cp is ", cp);

print(cout, "vp is ", vp);

return 0;

}

• Define print function template– Consistent interface across types– Just pass message, variable

• With this template we geti is 7

b is 0

ip is 0xfeea28f4

cp is hello, world!

vp is 0x8048adc

• Right back where we started?

template <typename T>

void print (ostream & os,

const char * message,

const T & t) {

os << message << t << endl;

}

Page 9: CSE 332: C++ template examples Concepts and Models Templates impose requirements on type parameters –Types that are plugged in must meet those requirements.

CSE 332: C++ template examples

Template Specialization: More Polymorphismtypedef char * charptr;

typedef int * intptr;

template <> void print

(ostream & os, const char * message,

const bool & b) {

os << message << std::boolalpha

<< b << endl;

}

template <> void print

(ostream & os, const char * message,

const charptr & s) {

os << message

<< reinterpret_cast<void *> (s);

if (s != 0) {

os << " (points to \""

<< s << "\")"; }

os << endl;

}

template <> void print

(ostream & os, const char * message,

const intptr & ip) {

os << message << ip;

if (ip != 0) {

os << " (points to " << *ip << ")"; }

os << endl;

}

• Specialize on individual typesbool char * int *– Notice the use of typedef

• With specialization, we geti is 7

b is false

ip is 0xfeebf064 (points to 7)

cp is 0x8048c30 (points to "hello, world!")

vp is 0x8048c30

• And, we can reuse the solution!

template <typename T>

void print (ostream & os,

const char * message,

const T & t) {

os << message << t << endl;

}

Page 10: CSE 332: C++ template examples Concepts and Models Templates impose requirements on type parameters –Types that are plugged in must meet those requirements.

CSE 332: C++ template examples

Concluding Remarks (1 of 2)

• The set of requirements that a class template or function template places on its parameterized types is called a concept in generic programming terminology

• Any type that meets those requirements is said to model the concept, and can be used in that template

• Concept refinement supports interface polymorphism• Push common code and variables up into non-

template base classes– Can help avoid subtle type errors– Can help reduce the size of the executable program

• Associated types expand the power of templates– E.g., used extensively in the C++ Standard Template Library

Page 11: CSE 332: C++ template examples Concepts and Models Templates impose requirements on type parameters –Types that are plugged in must meet those requirements.

CSE 332: C++ template examples

Concluding Remarks (2 of 2)

• Summary of generic programming ideas– Can use templates to plug different types into

function and class declarations/definitions– Can look at template code to come up with what the

requirements are for its parameterized types• Fortunately, someone has already done that for the STL• See Matt Austern’s book (CSE 532) for more details