140 likes | 207 Views
Learn about templates in C++, how they work, and how to overcome implementation problems when using templated functions. Find out how to template classes and handle template-related complexities efficiently in your code.
E N D
CS 240: Data Structures Monday, July 9th Templates
What are templates? • Templates are a language mechanism providing us the ability to create code that is not bound to a type.
bool isequal(int & left, int & right) { return(left == right); } What is we wanted to do this with char? float? double? Why would have to write a new function in each case. Example
Templates allow us to define the function without a “locked-in” type: Now, we can use isequal with any data types that have operator == properly defined. template<typename T> bool isequal(T & left, T & right) { return(left==right); } Templates, example
However…! • Templates provide additional complications when adding them to your code. • When you declare a templated function, the compiler only creates the appropriate function if someone uses it! • So…., how is that a problem?
Implementation Problems • Consider the files: isequal.h, isequal.cpp, main.cpp (using isequal(int,int)) • Normally, we compile as follows: • g++ -c isequal.cpp • g++ -c main.cpp • g++ -o main.exe main.o isequal.o • Linker error: isequal(int,int) doesn’t exist! • Huh? Is my compiler being dumb?
Implementation Problems • Well… when compiling a templated function, the compiler only creates the functions if they are used. • When you create isequal.o, no one has used isequal. Therefore, the interface exists (from the .h file) but no definitions exist! • Main.o tries to links with isequal.o but can’t find any definitions! We need to be able to create definitions when compiling main.cpp
Therefore, main.cpp must have access to the definitions. Main.cpp now includes both “isequal.h” and “isequal.cpp”. This also means that isequal.cpp needs conditional compilation. Optional (Out of scope of CS240): The use of “export” is part of the standard as a way to solve this problem. Most compilers (g++ included) do not implement export. This is part of a much larger issue. Problems
#ifndef ISEQUAL_H #define ISEQUAL_H template<typename T> bool isequal(T & left, T & right); #endif #ifndef ISEQUAL_CPP #define ISEQUAL_CPP #include”isequal.h” template<typename T> bool isequal(T & left, T & right) { return(left==right); } #endif main.cpp isequal.h #include<iostream> #include<string> #include”isequal.h” #include”isequal.cpp” using namespace std; int main() { int intx = 5, inty = 10, intz = 5; float floatx = 100, floaty = 200; float floatz = 100; string strx = “apple”, stry = “soda”; string strz = “apple”; cout << isequal(intx,inty) <<endl; cout << isequal(intx,intz) <<endl; cout << isequal(floatx,floaty) <<endl; cout << isequal(floatx,floatz) <<endl; cout << isequal(strx,stry) <<endl; cout << isequal(strx,strz) <<endl; return 0; } isequal.cpp
Makefile • Using the technique describes eliminates the need for any changes to the makefile. • There are alternative methods to handling the template problem that require compilation changes.
Templated classes • Classes can be templated too! • Add “template <typename T>” before the class prototype. • Add “template <typename T>” before each member function. • Each member function requires the class name to be “typed”.
#ifndef SAMPLE_H #define SAMPLE_H template<typename T> class sample { public: sample(); ~sample(); T somefunc(T,int,string); int otherfunc(T,T); }; #endif #ifndef SAMPLE_CPP #define SAMPLE_CPP #include”sample.h” template<typename T> sample<T>::sample() { } template<typename T> sample<T>::~sample() { } template<typename T> typename T sample<T>::somefunc(T a, int b, string c) { … } template<typename T> int sample<T>::otherfunc(T a, T b) { … } #endif sample.h sample.cpp Anytime you refer to sample, you must specify its type. The only exception are the original class name, constructors and destructors.
Using a templated class • To use sample: • sample<int> myintsample; • //Creates a sample object of type int • This is similar to the use of vector • vector<int> myintvector; • vector<string> mystringvector; • vector<vector<string> > mystringmatrix; • Yes, that extra space is needed.
More on templates • You can also use more than one type: • template <typename T, typename T2> • There are many other things that can be done. Many of these other techniques can be seen by examining the code related to the STL.