Presentation is loading. Please wait.

Presentation is loading. Please wait.

CSE 332: C++ templates and generic programming II Review: Concepts and Models Templates impose requirements on type parameters –Types that are plugged.

Similar presentations


Presentation on theme: "CSE 332: C++ templates and generic programming II Review: Concepts and Models Templates impose requirements on type parameters –Types that are plugged."— Presentation transcript:

1 CSE 332: C++ templates and generic programming II Review: 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

2 CSE 332: C++ templates and generic programming II Concept Refinement Motivates Overriding 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 How can we override function, class, and struct templates for specific parameterized types? C1 C2 T1T2 T3T4 C0 containment transitivity can substitute, e.g., T3 for T1

3 CSE 332: C++ templates and generic programming II Template Specialization: Overriding on Types Two examples –Fully specialize a function template to print different types –Partially specialize a struct template for iterator traits First example will refine output code several times –Ending up with a specialized reusable function template –Shows how to write fully specialized function templates –Can only fully (not partially) specialize a function template Second example shows the iterator traits idiom –Used by the STL to make pointers random access iterators –Wraps a typedef for an associated type in a struct –Allows partial specialization for specific pointer types

4 CSE 332: C++ templates and generic programming II First Example: Printing Different Types #include 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 We can improve on this!

5 CSE 332: C++ templates and generic programming II Improve the Output for bool #include 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 get i is 7 b is false ip is 0xfef2aa04 cp is hello, world! vp is 0x8048b0c But what about the pointers?

6 CSE 332: C++ templates and generic programming II Improve the Output for Pointers #include 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) << " (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, we don’t want to have to do all that over again the next time we want to print

7 CSE 332: C++ templates and generic programming II Refactor the Code with a Function Template #include 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 get i is 7 b is 0 ip is 0xfeea28f4 cp is hello, world! vp is 0x8048adc Right back where we started? template void print (ostream & os, const char * message, const T & t) { os << message << t << endl; }

8 CSE 332: C++ templates and generic programming II Fully Specialize to Override Function Templates typedef 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 (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 types bool char * int * –Notice the use of typedef With specialization, we get i 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 void print (ostream & os, const char * message, const T & t) { os << message << t << endl; }

9 CSE 332: C++ templates and generic programming II Second Example: Iterator Traits Start with a few concrete types for category tags –E.g., empty structs for input, output, fwd, bidir, and rand categories Those tags are used as associated types for iterators –Iterator category –Made available by partial specialization override for pointers struct input {}; // empty structs for type tags struct output {}; struct fwd : public input {}; // note inheritance struct bidir : public fwd {}; struct rand : public bidir {}; template struct iterator_traits {... typedef typename I::iterator_category iterator_category; }; template struct iterator_traits {... typedef rand iterator_category; }; template struct iterator_traits {... typedef rand iterator_category; }; (actually, random_access_iterator_tag )

10 CSE 332: C++ templates and generic programming II Algorithm Dispatching via Category Tags Static dispatching –Implementations provide different signatures –Iterator type is evaluated at compile-time –Links to the best implementation Notice how type tags are used // Based on Austern, pp. 38, 39 template void move (Iter i, Distance d, fwd) { while (d>0) {--d; ++i;} // O(d) } template void move (Iter i, Distance d, rand) { i += d; // O(1) } template void move (Iter i, Distance d) { move (i, d, iterator_traits :: iterator_category() ) } concrete tag (empty struct) type explicit constructor call concrete tag (empty struct) type

11 CSE 332: C++ templates and generic programming II Summary of Templates and Specialization 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 Fully specialize function templates (and fully or partially specialize class and struct templates) to override template behaviors, etc. for specific types


Download ppt "CSE 332: C++ templates and generic programming II Review: Concepts and Models Templates impose requirements on type parameters –Types that are plugged."

Similar presentations


Ads by Google