Advanced Software Engineering with C++ Templates Templates Thomas Gschwind <thg at zurich dot ibm dot com>
Templates § Polymorphisms § Specialization § Declaration and Use § Classes and Members § Ambiguities § An Example (pvector) Th. Gschwind. Advanced Software Engineering with C++ Templates. 91
Types of Polymorphisms § “Ad-hoc” • Overloading • Statically resolved by the compiler (using argument types) § Dynamic • Using virtual member functions • Method to be invoked identified during run-time (using a virtual method table) § Static or Parametric • Using templates • Function to be invoked identified statically • Concrete Functions/Classes are generated for the individual parameter types Th. Gschwind. Advanced Software Engineering with C++ Templates. 92
Templates – Why? § Allow to implement a function or class for a set of types and not just a ”single” hard-coded type • Writing min, max, swap, gcd, and lcm for all kinds of types is tedious • Sort of like Lisp, Smalltalk, Python, Ruby, you name it… • Just more efficiently § Support generic programming • Many functions are the same independently of the data type • Can influence the compiler’s code generation with specially crafted templates Th. Gschwind. Advanced Software Engineering with C++ Templates. 93
Templates: Declaration and Definition This is “old style”, typename is “more” template<class T> correct, but many people still prefer class. If you use an antiquated C++ compiler you may T min( T a, T b) { have to use class. return a<b ? a : b; } § Specify type as additional compile-time parameters • Types used with this template have to provide the routines used by the template • In this case, the comparison operator and a copy constructor § Are checked and resolved statically (during compile time) • Function calls can be resolved during compilation time § The definition must be available to the compiler Th. Gschwind. Advanced Software Engineering with C++ Templates. 94
Templates: Use § When invoking templates we can specify as additional (compile- time) parameter the type of the template to use template < typename T> T min(T a, T b) { return a<b?a:b; } const double pi=3.141596; void f() { min<double>(2.718282, 1.0); min<char>('a', 'z'); min<int>(1, 26); min<double>(pi, 2.718282); min<int>('a', 26); min<double>(2.718282, 1); } Th. Gschwind. Advanced Software Engineering with C++ Templates. 97
Templates: Use (cont’d) § In most cases, template parameters are deduced by the compiler • Deduction must be unambiguous • Otherwise, the ambiguity needs to be resolved manually template < typename T> template < typename T> inline T min(T a, T b) { inline T min(T a, T b) { return a<b?a:b; return a<b?a:b; } } const double pi=3.141596; const double pi=3.141596; void f() { void f() { min(2.718282, 1.0); // ok min(2.718282, 1.0); min('a', 'z'); // ok min('a', 'z'); min(1, 26); min(1, 26); // ok min(pi, 2.718282); min(pi, 2.718282); // ok min('a', 26); // error, ambiguous min('a', 26); min(2.718282, 1); min(2.718282, 1); // error, ambiguous } } Th. Gschwind. Advanced Software Engineering with C++ Templates. 98
Templates: Resolving Ambiguities § Unlike “normal” functions, there is no implicit conversion for parameters passed to templates § Explicit • If necessary min<int>('a', 26); • Or even if unnecessary min<const double>(pi, 2.718282); Th. Gschwind. Advanced Software Engineering with C++ Templates. 100
Mixing Templates and Non-Templates § Templates and non-templates can be mixed § Can define a template-based function min § And define a non template-based function min at the same time § Non-templates are preferred over templates if no type conversion necessary template < typename T> T min(T a, T b) { return a<b ? a : b; } double min(double a, double b) { return a<b ? a : b; } Th. Gschwind. Advanced Software Engineering with C++ Templates. 101
Templates: Resolving Ambiguities (cont‘d) § We can create separate helper functions • Helper functions may be based on the underlying template int min( int x, int y) { return min< int >(x, y); } double min( double x, double y) { return min< double >(x, y); } § This approach not only looks tedious but is also error-prone, clumsy, … Th. Gschwind. Advanced Software Engineering with C++ Templates. 102
min Template – A Problem? § What happens if we use it with (C-style) strings? cout << min("Hello", "World") << endl; § Based on the behavior of the other data types, we would expect a lexicographical Memory comparison of the arguments 0x1000 World § However, compares the addresses where the strings are 0x2000 Hello stored • Returns the string stored at the smaller address Th. Gschwind. Advanced Software Engineering with C++ Templates. 103
Specialization ( 1 st Attempt ) § Templates and non-templates can be mixed § Define a non template-based function min for C strings template < typename T> T min(T a, T b) { return a<b ? a : b; } char *min( char *a, char *b) { return strcmp(a, b)<0 ? a : b; } const char *min( const char *a, const char *b) { return strcmp(a, b)<0 ? a : b; } #include "min.h" void foo(char *x, char *y, const char *z) { cout << min(x,y) << endl; // yes cout << min(x,z) << endl; // yes cout << min<const char*>(x,z) << endl; // compiles but no } We are asking for the template, so we get the template … Th. Gschwind. Advanced Software Engineering with C++ Templates. 104
Template Specialization ( 2 nd and Final Attempt ) § C++ allows us to specialize an existing template for specific types template < typename T> T min(T a, T b) { return a<b ? a : b; } template<> char *min<char *>(char *a, char *b) { return strcmp(a, b)<0 ? a : b; } template<> const char *min<const char *>(const char *a, const char *b) { return strcmp(a, b)<0 ? a : b; } Compiler error; as we discussed, there is no #include "min.h" implicit parameter void foo(char *x, char *y, const char *z) { conversions for templates. cout << min(x, y) << endl; // yes cout << min(x, z) << endl; // error cout << min<const char*>(x, z) << endl; // yes } Th. Gschwind. Advanced Software Engineering with C++ Templates. 105
Templates: Classes and Members § Works exactly the same § Simply put template <typename T, typename U, …> in front of the declaration § It is even OK, to introduce new template parameters for individual member functions § Before C++17 no template parameter deduction for constructors • Template arguments need to be invoked when constructing an object pair<int, bool>(1, false) • Helper functions such as make_pair(1, false) § Template parameter deduction of constructors [C++17] • Allows developers to write pair(1, false) Th. Gschwind. Advanced Software Engineering with C++ Templates. 106
A Persistent pvector Class § We want to implement a persistent version of C++’s vector class § Reads all elements from a file in the constructor § Writes all elements back to the file in the destructor template < typename T> class pvector { string filename; vector<T> v; … public : pvector(string fname) : filename(fname) { readvector(); } ~pvector() { writevector(); } void push_back( const T &el) { v.push_back(el); } void pop_back() { v.pop_back(); } … Th. Gschwind. Advanced Software Engineering with C++ Templates. 107
A Persistent pvector Class (cont’d) template < typename T> class pvector { string filename; vector<T> v; void readvector() { ifstream ifs(filename); for (;;) { T x; ifs >> x; if(!ifs.good()) break; v.push_back(x); } } void writevector() { ofstream ofs(filename); typename vector<T>::iterator fst=v.begin(), lst=v.end(); while (fst!=lst) ofs << *fst++ << endl; OR starting with C++11, simply: } for ( const T &elem : v) ofs << elem << endl; … Th. Gschwind. Advanced Software Engineering with C++ Templates. 108
A Persistent pvector Class (cont’d) § What happens if we pass the pvector around? void foo(pvector< int > pv) { if (pv.size()>0) cout << pv[0] << endl; pv.push_back(17); } int main( int argc, char *argv[]) { pvector< int > pv("/tmp/pvector-int.txt"); foo(pv); } § Hence, maybe we want to disable the copy-constructor for pvector<T> Th. Gschwind. Advanced Software Engineering with C++ Templates. 109
BREAK? Th. Gschwind. Advanced Software Engineering with C++ Templates. 110
Advanced Software Engineering with C++ Templates Separate Compilation Thomas Gschwind <thg at zurich dot ibm dot com>
Separate Compilation § Compared to Java § Variables § Routines (Functions & Operators) § Types (Structures, Classes) § Makefiles Th. Gschwind. Advanced Software Engineering with C++ Templates. 112
Separate Compilation § Why? • Having only one source file is unrealistic • Break the code up into its logical structure • Reduction of compile time • Only changed parts need to be recompiled § How? • Use multiple source files • Compiler needs to know about • Functions and variables provided by other compilation units • Their signatures and types Th. Gschwind. Advanced Software Engineering with C++ Templates. 113
Recommend
More recommend