GridKa School 2013: Effective Analysis C++ Templates Introduction Jörg Meyer, Steinbuch Centre for Computing, Scientific Data Management KIT University of the State of Baden-Wuerttemberg and National Research Center of the Helmholtz Association www.kit.edu
What are templates? Why use them? Many algorithms are independent of data types e.g. sorting: algorithm does not care what to sort, as long as it knows how to compare things Template: allows to write code (functions, classes) for generic type Code gets instantiated for actual type at compile time (static polymorphism) no overhead at runtime no virtual calls, no common base class needed no conversion from void* no issues like with MACROS Meta programming: very powerful, STL full of templates 2
Why not to use templates? (not really ) error messages sometimes hard to read debugging cumbersome error.cpp:8:13: error: empty character constant error.cpp:9:17: error: empty character constant error.cpp: In instantiation of T foo(const T&) [with T = std::vector<std::basic_string<char> >] : error.cpp:15:8: required from here error.cpp:8:3: error: no matching function for call to std::vector<std::basic_string<char> >::begin(int) const error.cpp:8:3: note: candidates are: In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/vector:65:0, from error.cpp:1: /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:518:7: note: std::vector<_tp, _Alloc>::iterator std::vector<_tp, _Alloc>::begin() [with _Tp = std::basic_string<char>; _Alloc = std::allocator<std::basic_string<char> >; std::vector<_tp, _Alloc>::iterator = gnu_cxx:: normal_iterator<std::basic_string<char>*, std::vector<std::basic_string<char> > >; typename std::_vector_base<_tp, _Alloc>::pointer = std::basic_string<char>*] /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:518:7: note: candidate expects 0 arguments, 1 provided /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:527:7: note: std::vector<_tp, _Alloc>::const_iterator std::vector<_tp, _Alloc>::begin() const [with _Tp = std::basic_string<char>; _Alloc = std::allocator<std::basic_string<char> >; std::vector<_tp, _Alloc>::const_iterator = gnu_cxx:: normal_iterator<const std::basic_string<char>*, std::vector<std::basic_string<char> > >; typename gnu_cxx:: alloc_traits<typename std::_vector_base<_tp, _Alloc>::_Tp_alloc_type>::const_pointer = const std::basic_string<char>*] /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/stl_vector.h:527:7: note: candidate expects 0 arguments, 1 provided error.cpp:9:3: error: no matching function for call to std::basic_string<char>::length(int) const error.cpp:9:3: note: candidate is: In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/string:54:0, from error.cpp:2: /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/basic_string.h:718:7: note: std::basic_string<_chart, _Traits, _Alloc>::size_type std::basic_string<_chart, _Traits, _Alloc>::length() const [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>; std::basic_string<_chart, _Traits, _Alloc>::size_type = long unsigned int] /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/bits/basic_string.h:718:7: note: candidate expects 0 arguments, 1 provided 3
Function templates a+b: template <typename T> T sum(t const& a, T const& b) { return a+b; int main() { int i=2; int j=4; string s1 = "Hello "; string s2 = "World"; cout<<sum(i,j)<<endl; cout<<sum(s1,s2)<<endl; int sum(int const& a, int const& b) { return a+b; string sum(string const& a, string const& b) { return a+b; 4
Function templates (conversion) no automatic type conversion template <typename T> T sum(t const& a, T const& b) { return a+b; int main() { int i=2; double d=4.; cout<<sum(i,d)<<endl; //compile-time error cout<<sum<double>(i,d)<<endl; //ok 5
Function templates (C++11) new keyword: decltype template <typename T1, typename T2> decltype(a+b) sum(t1 const& a, T2 const& b) { return a+b; int main() { int i=2; double d=4.; cout<<sum(i,d)<<endl; //ok 6
Function templates (overloading) template function can be overloaded like normal functions: template <typename T> T sum(t const& a, T const& b) { return a+b; char const* sum(char const* a, char const* b) { cout<< char <<endl; return (string(a)+string(b)).c_str(); int main() { cout<<sum( Hello, World )<<endl; 7
Function templates (summary) function template: set of functions for different template types function template instantiated if being used with certain template argument template parameters can be deduced or explicitly being qualified function templates can be overloaded 8
Class templates parametrize classes by templates: template <typename T> class histogram { ; std::vector<t> bins; //content of histogram double xmin,xmax; //range for x-axis public: typedef T value_type; int Fill(double value, T weight=1) { unsigned int bin=findbin(value); bins[bin]+=weight; return bin; 9
Class templates (usage) usage of class templates already known from STL classes like vector histogram<float> H1F; H1F.Fill(3.14); histogram<double> H1D; double d = H1D.GetBinContent(2); 10
Class templates (class type) class type: histogram<t> template <typename T> class histogram { histogram(histogram<t> const&); // copy c tor histogram<t>& operator=(histogram<t> const&); //assignment ; 11 template <typename T> histogram<t>& histogram<t>::operator=(histogram<t> const&) {
Class templates (specialization) special implementation for T=big_number (partial specialization possible) class big_number; //user-defined class for huge numbers class big_number_allocator; //allocates space for big_number template <> class histogram<big_number> { std::vector<big_number,big_number_allocator> bins; //content of histogram ; double xmin,xmax; //range for x-axis public: typedef big_number value_type; int Fill(double value, big_number weight=1) 12
Class templates (default template argument) default type for second template argument: template <typename T, typename Alloc = allocator<t> > class histogram { ; std::vector<t,alloc> bins; //content of histogram histogram<int> hi; histogram<big_number,big_number_allocator> hbn; 13
Class template (summary) class template: implemented with some type parameters left open usage: vector<int> -> instantiates vector for type int class templates can be (partially) specialized class template arguments can have default values member functions of class templates get only instantiated if they are being used 14
Nontype templates value as template parameter #include<iostream> #include<vector> using namespace std; template <typename T, unsigned DIM> class vec { private: vector<t> v; public: vec() : v(dim,0) {; T& operator[](unsigned n) {return v[n]; T const& operator[](unsigned n) const {return v[n]; ; 15
Nontype templates // scalar product template<typename T, unsigned DIM> T operator*(vec<t,dim> const& a, vec<t,dim> const& b) { T ret = T(); for (int i=0;i!=dim;++i) ret+=a[i]*b[i]; return ret; int main() { vec<double,3> v1; v1[0]=1.; v1[1]=4.; v1[2]=2.; vec<double,3> v2; v2[0]=-1.; v2[1]=42.; v2[2]=11.; cout<<v1*v2<<endl; //189 vec<double,2> v3; cout<<v1*v3<<endl; //deduced conflicting values for non-type parameter DIM ( 3u and 2u ) 16
Nontype templates (summary) template parameter can be value instead of type works for template classes and functions argument for nontype parameter must not be floating-poing numbers, classes, string literals each instantiation defines a new type 17
Compiling and linking Instantiations of template functions require knowledge of the implementation implementation in header file or #include mytemplateclass.cpp alternatives: explicit instantiation; export 18
more on templates details on templates + inheritance template argument deduction traits, policy classes meta programming recursively defined templates variadic templates (C++11) much more 19