Download presentation
Presentation is loading. Please wait.
1
1 Generic Programming
2
2 Why? Sometimes a datum is just a datum Sometimes a datum is just a datum Operate on unrelated data types Operate on unrelated data types Container classes Container classes Equality operator Equality operator Swap method Swap method Sorting procedures Sorting procedures Code reuse Code reuse Build programs from small reusable generic parts Build programs from small reusable generic parts Avoid copying or reinventing the same code Avoid copying or reinventing the same code
3
3 Generic Programming Compile time parameters Compile time parameters Implementation Implementation Same code used for different parameter values Same code used for different parameter values Different code generated for different values Different code generated for different values Generic programming in ML Generic programming in ML Generics in ADA Generics in ADA Java 1.5 – GJ & Pizza Java 1.5 – GJ & Pizza C++ Standard Template Library C++ Standard Template Library Containers and Iterators Containers and Iterators
4
4 Generic programming Define software components with type parameters Define software components with type parameters A sorting algorithm has the same structure, regardless of the types being sorted A sorting algorithm has the same structure, regardless of the types being sorted Stack primitives have the same semantics, regardless of the Stack primitives have the same semantics, regardless of the objects stored on the stack. objects stored on the stack. Most common use: algorithms on containers: updating, iteration, search Most common use: algorithms on containers: updating, iteration, search C model: macros (textual substitution) C model: macros (textual substitution) Ada model: generic units and instantiations Ada model: generic units and instantiations C++ model: templates C++ model: templates ML and Java 1.5: type inference ML and Java 1.5: type inference
5
5 Parameterizing Software Components Construct Parameter Supplying parameter Construct Parameter Supplying parameter array values (bounds) declaring object array values (bounds) declaring object declaring subtype declaring subtype record discriminant object/subtype record discriminant object/subtype subprogram values (actuals) calling subprogram subprogram values (actuals) calling subprogram generic unit types, values instantiating generic unit types, values instantiating template classes, values instantiating, template classes, values instantiating, specializing specializing
6
6 Generics in Ada95 I/O for integer types. Identical implementation, but need separate procedures for strong-typing reasons. I/O for integer types. Identical implementation, but need separate procedures for strong-typing reasons. generic generic type Elem is range <> ; -- any integer type type Elem is range <> ; -- any integer type package Integer_IO is package Integer_IO is procedure Put (Item : Elem); procedure Put (Item : Elem);......
7
7 generic generic type Elem is private; -- compile time parameter type Elem is private; -- compile time parameter package Stacks is package Stacks is type Stack is private; type Stack is private; procedure Push (X : Elem; On : in out Stack); procedure Push (X : Elem; On : in out Stack); … private private type Cell; type Cell; type Stack is access Cell; -- linked list representation type Stack is access Cell; -- linked list representation type Cell is record type Cell is record Val : Elem; Val : Elem; Next : Ptr; Next : Ptr; end record; end record; end Stacks; end Stacks; A generic Package
8
8 Instantiations with Stacks; with Stacks; procedure Test_Stacks is procedure Test_Stacks is package Int_Stack is new Stacks (Integer); -- Package for integers package Int_Stack is new Stacks (Integer); -- Package for integers package Float_Stack is new Stacks (Float); -- Package for floats package Float_Stack is new Stacks (Float); -- Package for floats S1 : Int_Stack.Stack; -- an integer stack object S1 : Int_Stack.Stack; -- an integer stack object S2 : Float_Stack.Stack; -- a float stack object S2 : Float_Stack.Stack; -- a float stack object use Int_Stack, Float_Stack; -- ok, regular packages use Int_Stack, Float_Stack; -- ok, regular packages begin begin Push (15, S1); -- Int_Stack.Push Push (15, S1); -- Int_Stack.Push Push (3.5 * Pi, S2); Push (3.5 * Pi, S2);...... end Test_Stacks; end Test_Stacks;
9
9 Type parameters The generic type declaration specifies the class of types for which an instance of the generic will work: type T is private; -- any type with assignment (Non-limited) type T is private; -- any type with assignment (Non-limited) type T is limited private; -- any type (no required operations) type T is limited private; -- any type (no required operations) type T is range <>; -- any integer type (arithmetic operations) type T is range <>; -- any integer type (arithmetic operations) type T is (<>); -- any discrete type (enumeration or type T is (<>); -- any discrete type (enumeration or -- integer) -- integer) type T is digits <>; -- any floating-point type type T is digits <>; -- any floating-point type type T is delta <>; -- any fixed-point type type T is delta <>; -- any fixed-point type Within the generic, the operations that apply to any type of the class can be used. Within the generic, the operations that apply to any type of the class can be used. The instantiation must use a specific type of the class The instantiation must use a specific type of the class
10
10 A generic function generic generic type T is range <>; -- parameter of some integer type type T is range <>; -- parameter of some integer type type Arr is array (Integer range <>) of T; type Arr is array (Integer range <>) of T; -- parameter is array of those -- parameter is array of those function Sum_Array (A : Arr) return T; function Sum_Array (A : Arr) return T; -- Body identical to non-generic version -- Body identical to non-generic version function Sum_array (A : Arr) return T is function Sum_array (A : Arr) return T is Result : T := 0; -- some integer type, so literal 0 is legal Result : T := 0; -- some integer type, so literal 0 is legal begin begin for J in A’range loop -- some array type, so attribute is available for J in A’range loop -- some array type, so attribute is available Result := Result + A (J); -- some integer type, so “+” available. Result := Result + A (J); -- some integer type, so “+” available. end loop; end loop; return Result; return Result; end; end;
11
11 Instantiating a generic function -- Define types for Apple Production -- Define types for Apple Production type Apple is range 1.. 2 **15 - 1; type Apple is range 1.. 2 **15 - 1; type Production is array (1..12) of Apple; type Production is array (1..12) of Apple; -- Define types for Sick Days type Sick_Days is range 1..5; type Sick_Days is range 1..5; type Absences is array (1.. 52) of Sick_Days; type Absences is array (1.. 52) of Sick_Days; -- Instantiate definite functions from the generic -- Instantiate definite functions from the generic function Get_Crop is new Sum_array (Apple, Production); function Get_Crop is new Sum_array (Apple, Production); function Lost_Work is new Sum_array (Sick_Days, Absences); function Lost_Work is new Sum_array (Sick_Days, Absences);
12
12 Generic private types Generic private types Only available operations are assignment and equality. Only available operations are assignment and equality. generic generic type T is private; type T is private; procedure Swap (X, Y : in out T); procedure Swap (X, Y : in out T); procedure Swap (X, Y : in out T) is procedure Swap (X, Y : in out T) is Temp : constant T := X; Temp : constant T := X; begin begin X := Y; X := Y; Y := Temp; Y := Temp; end Swap; end Swap;
13
13 Subprogram parameters Subprogram parameters A generic sorting routine should apply to any array whose components are comparable, i.e. for which an ordering predicate exists. This class includes more that the numeric types: A generic sorting routine should apply to any array whose components are comparable, i.e. for which an ordering predicate exists. This class includes more that the numeric types: generic generic type T is private; -- type parameter type T is private; -- type parameter with function “<“ (X, Y : T) return Boolean; -- subprogram parameter with function “<“ (X, Y : T) return Boolean; -- subprogram parameter type Arr is array (Integer range <>) of T; -- type parameter type Arr is array (Integer range <>) of T; -- type parameter procedure Sort (A : in out Arr); procedure Sort (A : in out Arr); procedure Sort(A: in out Arr) is -- A Procedure Body Min: Index; Min: Index; Temp : T;-- Using type parameter Temp : T;-- Using type parameter begin begin for I in A’first.. Index’Pred(A’Last) loop for I in A’first.. Index’Pred(A’Last) loop Min := I; Min := I; for J in Index’Succ(I).. A’Last loop for J in Index’Succ(I).. A’Last loop if A(J) < A(Min) then Min := J; end if; -- Using subprogram parameter if A(J) < A(Min) then Min := J; end if; -- Using subprogram parameter end loop; end loop; Temp := A(I); A(I) := A(Min); A(Min) := Temp; -- swap Temp := A(I); A(I) := A(Min); A(Min) := Temp; -- swap end loop; end loop; end Sort; end Sort;
14
14 Supplying subprogram parameters Supplying subprogram parameters The actual must have a matching signature, not necessarily the same name: The actual must have a matching signature, not necessarily the same name: -- instantiate ascending and descending sort for integers -- instantiate ascending and descending sort for integers procedure Sort_Up is new Sort (Integer, “<“, …); procedure Sort_Up is new Sort (Integer, “<“, …); procedure Sort_Down is new Sort (Integer, “>”, … ); procedure Sort_Down is new Sort (Integer, “>”, … ); -- instantiate sort by seniority for employees -- instantiate sort by seniority for employees type Employee is record.. end record; type Employee is record.. end record; function Senior (E1, E2 : Employee) return Boolean; function Senior (E1, E2 : Employee) return Boolean; function Rank is new Sort (Employee, Senior, …); function Rank is new Sort (Employee, Senior, …);
15
15 Value parameters Value parameters Useful to parametrize containers by size: Useful to parametrize containers by size: generic generic type Elem is private; -- type parameter type Elem is private; -- type parameter Size : Positive;-- value parameter Size : Positive;-- value parameter package Queues is package Queues is type Queue is private; type Queue is private; procedure Enqueue (X : Elem; On : in out Queue); procedure Enqueue (X : Elem; On : in out Queue); procedure Dequeue (X : out Elem; From : in out Queue); procedure Dequeue (X : out Elem; From : in out Queue); function Full (Q : Queue) return Boolean; function Full (Q : Queue) return Boolean; function Empty (Q : Queue) return Boolean; function Empty (Q : Queue) return Boolean; private private type Contents is array (Natural range <>) of Elem; -- indefinite type Contents is array (Natural range <>) of Elem; -- indefinite type Queue is record type Queue is record Front, Back: Natural; Front, Back: Natural; C : Contents (0.. Size); -- An array of the specified size C : Contents (0.. Size); -- An array of the specified size end record; end record; end Queues; end Queues; Small_Integer_Queue_Package is new Queues(Integer, 10); Small_Integer_Queue_Package is new Queues(Integer, 10);
16
16 Packages as parameters If interface includes a type and its operations, the parameter can be a single generic package: If interface includes a type and its operations, the parameter can be a single generic package: generic generic type Real is digits <>; -- any floating type type Real is digits <>; -- any floating type package generic_complex_types is package generic_complex_types is -- complex is a record with two real components -- complex is a record with two real components -- package declares all complex operations: +, -, Re, Im... -- package declares all complex operations: +, -, Re, Im... end generic_complex_types; end generic_complex_types; We also want to define a package for elementary functions (sin, cos, etc.) on complex numbers. We need the complex operations, which are parametrized by the corresponding real value. We also want to define a package for elementary functions (sin, cos, etc.) on complex numbers. We need the complex operations, which are parametrized by the corresponding real value.
17
17 The instantiation requires an instance of the parameter with generic_complex_types; with generic_complex_types; generic generic with package compl is new generic_complex_types (<>); with package compl is new generic_complex_types (<>); package generic_complex_elementary_functions is package generic_complex_elementary_functions is -- trigonometric, exponential, hyperbolic functions. -- trigonometric, exponential, hyperbolic functions. end generic_complex_elementary_functions; end generic_complex_elementary_functions; Instantiate complex types with long_float components: Instantiate complex types with long_float components: package long_complex is new generic_complex_type (long_float); package long_complex is new generic_complex_type (long_float); Instantiate complex functions for long_complex types: Instantiate complex functions for long_complex types: package long_complex_functions is package long_complex_functions is new generic_complex_elementary_functions (long_complex); new generic_complex_elementary_functions (long_complex);
18
18 Generics in C++ (Templates) Template is a parameterized class or function definition Template is a parameterized class or function definition Compiler creates a separate class or function definition for each unique set of parameters with which it is instantiated Compiler creates a separate class or function definition for each unique set of parameters with which it is instantiated Same code not used for multiple types Same code not used for multiple types Originally implemented using macros Originally implemented using macros Simple Syntax Simple Syntax template ‘ ’ class_def | func_def template ‘ ’ class_def | func_def Parameters may be types or values Parameters may be types or values
19
19 A Template in C++ template class Vector { template class Vector { public: public: Vector (size_t n); // constructor Vector (size_t n); // constructor T& operator [ ] (size_t index); // subscript operator T& operator [ ] (size_t index); // subscript operator private: private: … // implementation details … // implementation details }; }; Vector V1 (100); // instantiation Vector V1 (100); // instantiation typedef Vector Dept; // named type instance typedef Vector Dept; // named type instance
20
20 Class and value parameters template class Buffer { template class Buffer { T v [i]; -- storage for buffer T v [i]; -- storage for buffer int sz; -- total capacity int sz; -- total capacity int count; -- current contents int count; -- current contents public: public: Buffer( ) : sz (i), count (0) { }; Buffer( ) : sz (i), count (0) { }; T read (); T read (); void write (T elem); void write (T elem); }; }; Buffer picture; -- instance for a graphics app. Buffer picture; -- instance for a graphics app.
21
21 Template hopes for the best template class List { struct Link { // for a list node struct Link { // for a list node Link* pre; // doubly linked Link* pre; // doubly linked Link* succ; Link* succ; T val; T val; Link (Link* p, s, const T& v): pre (p), succ(s), val (v) { }; } Link (Link* p, s, const T& v): pre (p), succ(s), val (v) { }; } Link * head; Link * head; public: public: void print_all () { for (Link*p = head; p; p=p->succ) void print_all () { for (Link*p = head; p; p=p->succ) cout val val << ‘\n’; // operator<< better exist for T! }; };
22
22 Function templates Instantiated implicitly at point of first call. Instantiated implicitly at point of first call. template void sort (vector & v) {..}; template void sort (vector & v) {..}; void testit (vector & vi) { void testit (vector & vi) { sort (vi); sort (vi); // can also write sort (vi); // can also write sort (vi); }; };
23
23 Functions and function templates Templates and regular functions overload each other: Templates and regular functions overload each other: template class complex {…}; template class complex {…}; template T sqrt (T); // function template for any T template T sqrt (T); // function template for any T template complex sqrt (complex ); // specialization template complex sqrt (complex ); // specialization double sqrt (double); // regular function double sqrt (double); // regular function void testit (complex cd) { void testit (complex cd) { sqrt (2); // sqrt : specialization of template sqrt (2); // sqrt : specialization of template sqrt (cd); // sqrt( (complex ): specialization sqrt (cd); // sqrt( (complex ): specialization sqrt (2.0); // sqrt (double): regular function sqrt (2.0); // sqrt (double): regular function }; };
24
24 Iterators and Containers Containers are standard data structures to manage collections Containers are standard data structures to manage collections Arrays, Linked Lists, Balanced Trees, etc. Arrays, Linked Lists, Balanced Trees, etc. Operations include: insert, delete, search, count Operations include: insert, delete, search, count Standard algorithms over collections use iterators: Standard algorithms over collections use iterators: template Iterator { template Iterator { Iterator (Coll over) {..}; // build iterator for given collection Iterator (Coll over) {..}; // build iterator for given collection Elem First_Elem (); // start iteration Elem First_Elem (); // start iteration Elem Next_Elem (); // move to next element in collection Elem Next_Elem (); // move to next element in collection bool done (); // termination condition bool done (); // termination condition }; };
25
25 Standard Template Library Generic Library for C++ Generic Library for C++ Well-structured components Well-structured components Orthogonal design Orthogonal design Based on firm theoretical foundations Based on firm theoretical foundations Efficient implementation Efficient implementation Components Components Algorithms – define computational procedures Algorithms – define computational procedures Containers – manage a set of objects Containers – manage a set of objects Iterators – means of traversing containers Iterators – means of traversing containers Function Objects – encapsulate functions in objects Function Objects – encapsulate functions in objects Adaptors – adapts components to provide a different interface Adaptors – adapts components to provide a different interface
26
26 Common Operators STL defines !=, >, >=,, >=, <= from == and < template template inline bool operator!= (const T& x, const T& y) { inline bool operator!= (const T& x, const T& y) { return !(x == y); } return !(x == y); } template template inline bool operator>= (const T& x, const T& y) { inline bool operator>= (const T& x, const T& y) { return !(x < y); } return !(x < y); } Programmer only needs to define == and < Programmer only needs to define == and < Sound and logically consistent semantics Sound and logically consistent semantics
27
27 STL Algorithms Algorithms operate on iterators Algorithms operate on iterators Apply a function to every element in a container Apply a function to every element in a container template template void for_each(iter first, iter last, function f); void for_each(iter first, iter last, function f); APL-like Reduction APL-like Reduction template template void accumulate(iter first, iter last, T init, function f); void accumulate(iter first, iter last, T init, function f); Orthogonal Orthogonal Algorithm can operate on any container that supports basic iterators Algorithm can operate on any container that supports basic iterators The actual iterator provided may be more complex The actual iterator provided may be more complex
28
28 STL Containers Sequence, list, dequeue, set, map, string, etc. Sequence, list, dequeue, set, map, string, etc. Instantiated with type parameter Instantiated with type parameter typedef list int_list; int_list a_list; All access is based on iterators All access is based on iterators Containers include standard iterators: Containers include standard iterators: begin() // returns iterator pointing to first element in container begin() // returns iterator pointing to first element in container end() // returns iterator pointing to first location after end of container end() // returns iterator pointing to first location after end of container Allows uniform access to all kinds of containers Allows uniform access to all kinds of containers for (c.iterator I = c.begin(); I != c.end(); ++I) { … }
29
29 STL Iterators Iterators are a generalization of the semantics of pointers (and arrays) in C Iterators are a generalization of the semantics of pointers (and arrays) in C Categories of iterators Categories of iterators Input Input Output Output Forward Forward Bidirectional Bidirectional Random Access Random Access Operations on Iterators include: Operations on Iterators include: =, ==, !=, ++(pre and post), *(dereference) =, ==, !=, ++(pre and post), *(dereference) Bidirectional iterators also support: --(pre and post), +, -, etc. Bidirectional iterators also support: --(pre and post), +, -, etc.
30
30 Function Class and Adaptors Function classes are classes for which the operator () is defined, allowing the object itself to be called as a function Function classes are classes for which the operator () is defined, allowing the object itself to be called as a function // A function of type int bool // A function of type int bool unary_function unary_function // A function of type (int x int) bool // A function of type (int x int) bool binary_function binary_function Adaptors allow a particular interface to be wrapped around an object. Adaptors allow a particular interface to be wrapped around an object. Stack adaptor can be supported by a vector, list or deque. Stack adaptor can be supported by a vector, list or deque. Stack myStack; Stack myStack;
31
31 Using STL main (int argc, char *argv[]) { int *last; // integer iterator int *last; // integer iterator int result; int result; int test_seq[20];// space for test data int test_seq[20];// space for test data last = test_seq + 20; last = test_seq + 20; ostream_iterator out_stream(cout, “”); ostream_iterator out_stream(cout, “”); // use generic library functions, such as IotaGen (like APL iota) to generate test data // use generic library functions, such as IotaGen (like APL iota) to generate test data generate(test_seq, last, IotaGen (0)); generate(test_seq, last, IotaGen (0)); copy(test_seq, last, out_stream); copy(test_seq, last, out_stream); // output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 // output: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 result = accumulate(test_seq, last, 0); result = accumulate(test_seq, last, 0); cout << result << endl; cout << result << endl; // 190 // 190}
32
32 GJ and Pizza Added ML style Generics to Java Added ML style Generics to Java Based on type inference in ML Based on type inference in ML Ensures no run-time errors Ensures no run-time errors Allows same code to execute for different types Allows same code to execute for different types Syntax similar to C++ Templates Syntax similar to C++ Templates Compatible with legacy Java Compatible with legacy Java New Container Libraries New Container Libraries Based on GJ and Pizza Based on GJ and Pizza Research at Bell Labs and Elsewhere Research at Bell Labs and Elsewhere Phillip Wadler Phillip Wadler
33
33 Generic Java Bad old ugly Java Bad old ugly Java Vector v = new Vector(10); Vector v = new Vector(10); v.put(Integer(9)); v.put(Integer(9)); v.put(String(“abc”)); v.put(String(“abc”)); String s = (String) v.get(n); // Run-time error if object is not a string! String s = (String) v.get(n); // Run-time error if object is not a string! Good new elegant Java 1.5 Good new elegant Java 1.5 Vector v = new Vector (10); Vector v = new Vector (10); v.put(Integer(9)); // Compile time error v.put(Integer(9)); // Compile time error v.put(String(“abc”)); v.put(String(“abc”)); String s = v.get(n); // No cast required String s = v.get(n); // No cast required
34
34 Creating Generic Classes public class Stack { Vector store; // Actual storage structure Vector store; // Actual storage structure public Stack(int n) {store = new Vector (n);} public Stack(int n) {store = new Vector (n);} public Stack() {store = new Vector (10);} public void Push(T e) { store.add(e);} // Only accepts elements of type T public void Push(T e) { store.add(e);} // Only accepts elements of type T public T Pop() {// Returns type T public T Pop() {// Returns type T if (store.isEmpty()) { if (store.isEmpty()) { throw new StackEmptyException() throw new StackEmptyException() } else { } else { return remove(store.size-1); return remove(store.size-1); } } }
35
35 Using Generic Classes Stack si; // Create an integer stack Stack si; // Create an integer stack Stack ss; Stack ss; si.push(4); // OK, si is integer stack si.push(4); // OK, si is integer stack ss.push(“Hello”); // OK, ss is string stack ss.push(“Hello”); // OK, ss is string stack ss.push(3); // Compile time error ss.push(3); // Compile time error int i = si.pop(); // No cast, no runtime error int i = si.pop(); // No cast, no runtime error
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.