View
214
Download
0
Embed Size (px)
Citation preview
1
GenericityGenericity
C++ Templates
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”
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
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
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;}
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++
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;}
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];
}}
...};
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);
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!
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;}
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;}
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}
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
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}
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;}
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
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.
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
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
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
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;}
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; }
};
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?
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));}
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
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.
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: ......
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