120 likes | 428 Views
Templatization In CPSC152, we saw a class vector in which we could specify the type of values that are stored: vector< int > intData( 30 ); vector< string > stringData( 10 ); vector is an example of a templatized class.
E N D
Templatization In CPSC152, we saw a class vector in which we could specify the type of values that are stored: vector< int > intData( 30 );vector< string > stringData( 10 ); vector is an example of a templatized class. The type of data stored in the vector is specified when we declare an instance of the vector. Templatization allows us to create collection classes that work for any type of data.
In 252 we have used atypedefto define theItem_typethat is stored in a collection. • typedef int Item_type; • class Queue { • bool enqueue(const Item_type &item); • Item_type dequeue(); • } • Issues: • Changing the type of data stored in the collection means editing the .h file. • We can only have collections of one kind of data at a time. • In C++ we can create templatized functions and templatized classes.
Function templates – swap ints Suppose we want to swap the value of two integers: void swap( int& num1, int& num2 ){ int temp = num1; num1 = num2; num2 = temp;}
Function templates – swap strings We can overload swap void swap( string& str1, string& str2 ){ string temp = str1; str1 = str2; str2 = temp;} This gets tedious (and error prone) Templatization allows us to define a version of theswapfunction that will work with any data type…
Function templates – templatized swap template< typename Item_type >void swap( Item_type& item1, Item_type& item2 ){ Item_type temp = item1; item1 = item2; item2 = temp;} Note: the first line of the above function definition could be replaced with: template< class Item_type > But the typename keyword is perhaps more precise.
Templatized functions - calling int num1 = 10, num2 = 20;string str1 = “hello”, str2 = “world”; swap( num1, num2 ); // compiler generates a // void swap( int&, int& ); // version of functionswap( str1, str2 ); // compiler generates a // void swap( string&, string& ); // version of functionswap( num1, str2 ); // syntax error: data types of // parameters do not matchNote: the templatized function must be compiled at the same time as the client code. swap.cppcan be#include’d at the head of the client code.
Templatized functions – calling explicitly int num1 = 10, num2 = 20;string str1 = “hello”, str2 = “world”; swap<int>( num1, num2 ); swap<string>( str1, str2 ); This points out the problem with swap ( num1, str2 ); What type should you supply? swap<???>( num1, str2 );
Class Templates The declaration of a templatized version of our Queue class may look as follows: template <typename Item_type> class Queue { bool enqueue(const Item_type &item); Item_type dequeue(); } The body of the class declaration will look no different from the version that uses atypedefto defineItem_type. However, the syntax used to define each of the member functions is a little more involved…
The function definition for the constructor will look as follows: template< typename Item_type >Queue< Item_type >::Queue(){ …} and theenqueue(…)function looks like: template< typename Item_type >bool Queue<Item_type>::enqueue(const Item_type& item) { …} C++ syntax at its finest!A templatized version of ourQueueclass will be found on the web.
A Style Suggestion: Since the entire templatized class needs to be compiled with the client code that uses it, and since the syntax for separate method bodies is ugly, and since we normally include .h files (and not .cpp files), then one can include the bodies of the templatized functions in the class definition. Many of the examples use the convention of a .template file, which is included in lieu of a .h file.
In Queue.template (or Queue.h): • template< typename Item_type >class Queue { • Queue(){ front = count = 0; • } • bool enqueue(const Item_type& item) { • if (full()) • return false; • // Only shuffle the elements down if you must • if (front + count >= CAPACITY) { • for (int i = 0; i < count; i++) • data[i] = data[front + i]; • front = 0; • } • data[front + count++] = item; • return true; • } • … • }
Using the templatized Queue class Queue<int> intQ; Queue<string> stringQ; intQ.enqueue(34); stringQ.enqueue(“abc”); Attempts to mix types generate compiler errors: stringQ.enqueue(34); Queue-driver.cpp:78: error: invalid conversion from `int' to `const char*' Queue-driver.cpp:78: error: initializing argument 1 of ` std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]'