1genericity c++ templates. 2 parametric polymorphism allows definitions to be parametrized at...

29
1 Genericity Genericity C++ Templates

Post on 21-Dec-2015

216 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

1

GenericityGenericity

C++ Templates

Page 2: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

2

Parametric PolymorphismParametric Polymorphism

Allows definitions to be parametrized at compile-time Such a definition is actually a “function” that returns

a new program element(method, class, etc.)

Template parameters = The arguments of this “function” AKA: type parameters

Instantiation of a template == evaluating the “function”

Page 3: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

3

Template Instantiation in C++Template Instantiation in C++

The compiler recompiles the template definition Substitutes the formal template parameters with the

actual parameters Generates new object code

Almost no compilation when the definition is read Most compilation work is at each instantiation point

The template definition must be part of the source code That is: #included from an .h file Supporting separate compilation of templates is too

difficult in practice

Page 4: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

4

C++ Function TemplatesC++ Function Templates A function can have type parameters

template<typename T> T* create() { return new T(); } void f() { string* sp = create<string>(); }

we use create() thru explicit instantiation We specify the actual types inside a pair of < >

In some cases the compiler can deduce the template parameterstemplate<typename T> void print(T& t) { cout << t << endl; }void g() { print(5); }

We use print() thru implicit instantiation Possible if a type parameter is also a value parameter Make overload resolution more difficult Introduced later

Page 5: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

5

C++ Class TemplatesC++ Class Templatestemplate<class Type> class Stack {

Type buff[50]; int sp;

public: Stack(void): sp(0) {} void push(const Type &e) {

buff[sp++] = e;}Type pop(void) { return buff[--sp]; }int empty(void) const { return sp == 0;}int full(void) const{ return sp == 50; }

};

template <class T> Stack<T>::push(T val){if (sp >= size) {

error("Stack is full");return;

} buff[sp++] = val;}

Page 6: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

6

Kind of ParametersKind of ParametersGenerics are “routines executed at compile time and produce source code”. Therefore, all parameters must be entities that are known at compile time.

Type: most frequent and most important. All languages which support genericity allow type parameter.

Numerical Constant: e.g., the integer constant 3. Useful for building generic arrays.

Variables: Constant: Address of a variable in C++

Routine: Constant: Address of function in C++

Page 7: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

7

A Template Taking a ConstantA Template Taking a Constanttemplate<int N>struct FixedArray { double values[N]; int size() { return N; } // Could be static};

int main(int, char**) { FixedArray<10> arr; arr.values[0] = 3.14; cout << "first element=" << arr.values[0] << endl; cout << "size=" << arr.size() << endl; return 0;}

Page 8: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

8

A Template Taking a Function Pointer A Template Taking a Function Pointer

typedef void (*ErrorFunction)(const char *);

template <class Type, ErrorFunction error>class Array {

size_t n; Type *buff;public:

Array(size_t n_): n(n_), buff(new Type[n]){if ((buff == (Type *)0) error("Memory

failure");}

Type & operator [] (size_t i) {if (i >= n){

error("Array overflow"); return buff[i];

}}

...};

Page 9: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

9

Using Function Arguments to TemplatesUsing Function Arguments to Templates

#include <stdlib.h>#include <iostream.h>

void err_abort(const char *msg) {

cerr << "Error: " << msg <<". Aborting!\n";exit(1);

}

typedef Array<int, err_abort> SafeIntArray;...SafeIntArray a(20);

Page 10: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

10

String Arguments to Templates?String Arguments to Templates?

template <class Type, const char *Name>class NamedType: public Type { public: const char *name() { return Name; }};

#define NAMED(T) NamedType<T, #T>typedef NAMED(MyClass) MyNamedClass;

Does not work! Considerconst char *const Hello1 = "Hello";const char *const Hello2 = "Hello";

Then, Hello1 and Hello2 are not (usually) the same!

Page 11: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

11

A Template Taking a TypeA Template Taking a Typetemplate<typename T>struct Pair { void set(const T& x, const T& y) { a = x; b = y; } void print() { cout << a << "," << b << endl; } private: T a, b; };

typedef Pair<char*> StrPair; // Instantiate Pair, // pass char* as an argument

typedef Pair<int> IntPair; int main(int, char**) { StrPair sp; IntPair ip; sp.set("ab", "cd"); sp.print(); ip.set(10, 20); ip.print(); return 0;}

Page 12: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

12

SpecializationSpecializationtemplate<typename T>struct Pair { void set(const T& x, const T& y) { a = x; b = y; } void print() { cout << a << "," << b << endl; } private: T a, b; };

template<>struct Pair<bool> { void set(bool x, bool y) { v = (x?1:0) + (y?2:0); } void print() { cout << (v&1) << "," << (v&2) << endl; } private: int v;}; int main(int, char**) { Pair<bool> pb; pb.set(true, false); pb.print(); Pair<char> pc; pc.set('x', 'y'); pc.print(); return 0;}

Page 13: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

13

A Non Conforming Specialization is LegalA Non Conforming Specialization is Legaltemplate<typename T>struct Pair { void set(const T& x, const T& y) { a = x; b = y; } void print() { cout << a << "," << b << endl; } private: T a, b; };

template<>struct Pair<bool> { void set(bool x, bool y) { v = (x?1:0) + (y?2:0); } public: int v;}; void doSomething() { Pair<bool> pb; pb.set(true, false); cout << pb.v << endl; Pair<char> pc; pc.set('x', 'y'); pc.print(); pb.print(); // Error. Pair<bool>::print() is undefined}

Page 14: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

14

C++ Templates: Interim SummaryC++ Templates: Interim Summary A template is a “function”

Arguments: types, constants Return value : A new class or a new function

Recognized by the compiler

The template is recompiled with each Instantiation

Specialization == “if” Different result based on the actual arguments

Page 15: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

15

Compile Time ComputationsCompile Time Computationstemplate <int N>struct Factorial { enum { value = N * Factorial<N - 1>::value };}; template <>struct Factorial<0> { enum { value = 1 };};

void foo(){ int x = Factorial<4>::value; // == 24 int y = Factorial<0>::value; // == 1}

Page 16: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

16

A Non-Terminating CompilationA Non-Terminating Compilationtemplate<typename T>struct Loop{ typedef typename Loop<Loop<T> >::Temp Temp;};

int main(int, char**) { Loop<int> n; return 0;}

Page 17: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

17

Constraints on Parameters?Constraints on Parameters?

Constant parameters: type of argument. InC++, the usual type conversions are allowed, e.g.,

if formal parameter to class template is of type T*, then actual parameter can be of type T1*,provided that T1 is derived from T.

Type of parameters: what is the type of a type?

Main approaches: No restrictions Dynamic checking Explicit list of constraints By derivation

Page 18: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

18

No Restriction on ArgumentsNo Restriction on Arguments

Any type is allowed. Generic limited to what can be done on all types.

Example: Early versions of Eiffel.

Advantages: Code sharing.

Disadvantages: Restrictions on generics. Only the most primitive operations are allowed on

arguments.

Page 19: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

19

Dynamic Checking of ArgumentsDynamic Checking of Arguments

(The generic equivalent of dynamic typing.) The compiler tries to instantiate a template. If an invalid operation is attempted, then an error message is issued.

Example: C++

Advantages: Compiler writing is easy Flexibility to programmer

Disadvantages: Extra burden on the library designer Surprises to the user Constraints are dependent on actual usage Difficult to understand Some parts of static type checking are deferred to link time

Page 20: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

20

Explicit List of ConstraintsExplicit List of Constraints

The programmer specifies the set of operations that might be used on a type argument.

Example: Ada Advantages:

Readability No surprises

Disadvantages: Lists could be very long Less flexibility in the design of classes List of operations instead of abstraction of functionality

Page 21: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

21

Constraints on Type Parameters Constraints on Type Parameters ((contcont.).)

By derivation. The actual parameter must be the same or inherited from the declared type.

Example: Current Eiffel

Advantages: Code sharing OOP Like

Abstraction at the right level Disadvantages:

Could lead to over use of inheritance Inheritance is used for abstraction, not only for subtyping

Too specific parameter types Too general parameter types Not appropriate for built-in types

Page 22: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

22

QuizQuiz: : What are the 6 Constraints?What are the 6 Constraints?

template <class T> T avg(const T a[], int size){

T sum = a[0];

for (int i = 1; i < size; i++)sum += a[i];

return sum/size;}

Page 23: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

23

QuizQuiz: : The 5 ConstraintsThe 5 Constraints

template<class Type> class Stack {

Type buff[50]; int sp;

public: Stack(void): sp(0) {} void push(const Type &e) {

buff[sp++] = e;}Type pop(void) { return buff[--sp]; }int empty(void) const { return sp == 0; }int full(void) const { return sp == 50; }

};

Page 24: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

24

InstantiationInstantiation Implicit: Instantiation occurs whenever an instance is

required. Examples: ML, Function Templates in C++. Advantages: simple syntax. Disadvantages: Surprises. Requires a complex type inference

engine: can be in some conditions an undecidable problem. Implicit Usage: Instantiation occurs whenever the

programmer uses an instance of a generic for the first time. Examples: Class templates in C++. Optional in function templates

in C++ (since November 1993). Advantages: Balance between convenience and accuracy. Disadvantages: Confusing error messages. Relatively complex

syntax. Obscure environment of instantiation. Explicit: Programmer must instantiate a generic priorly to

using it. Examples: Ada. C++ new features: explicit instantiation. Advantages: Explicit. No surprises. Disadvantages: What if the same generic is instantiated twice?

Page 25: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

25ExampleExample: : Function Template Function Template InstantiationInstantiation

template <class T> T max(T a,T b) { return a > b ? a : b; }

int main(){

extern int f(int);int i(10), j = f(i);int k = max(i, j);

extern double cos(double);double r(0.5), s(cos(r));double t = max(r, s);

return max(k, int(1/t));}

Page 26: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

26

Function Return Type?Function Return Type?The function return type is not used for resolving ambiguities

template <class T>inline long double sum(const T a[], int size){ return (long double) avg(a, size) * size;}

template <class T> inline T sum(const T a[], int size) {

return avg(a, size) * size;}

The compiler will complain if the sum template is used

Page 27: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

27

Class Template InstantiationClass Template Instantiation

Whenever a new particular version of the class template Stack is used (such as Stack<int> or Stack<char*>), the compiler will arrange for a version of that template to be instantiated.

Each instantiation of template class is a class by itself. The template classes Stack<int>, Stack<Complex>,

and Stack<void*> are different classes. There may be compile time errors when a template is

instantiated. Only the members that are used should be instantiated. In a single compilation unit, instantiation of a template

occurs only once for each particular set of values of the arguments.

Page 28: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

28

Explicit Instantiation in CExplicit Instantiation in C++++

New feature: adopted in San Jose, November 1993. Ability to specify environment for instantiation. Pre-create libraries of instantiations. Independent of

changes in the environment of the using programs.

Some implementations: multiple explicit instantiation may produce an error message or warning.

Explicit instantiation of a class template: forces instantiation of all its members, whereby forcing constraints.

template class Stack<int>;

Explicit instantiation of a function member of a class template:

template void Stack<int>::push(int &);

Explicit instantiation of a function template: ......

Page 29: 1Genericity  C++ Templates. 2 Parametric Polymorphism Allows definitions to be parametrized at compile-time Such a definition is actually a “function”

29

Explicit Instantiation of Function Explicit Instantiation of Function TemplateTemplate

Given the function template:template <class T> T max(T a, T b) {

return a > b ? a : b;}

Explicit Instantiation is:

template int max<int>(int, int);// naming the argument

template int max(int, int);// the argument is deduced here