C++ for Scientists - Technische Universität Dresden
C++ for Scientists - Technische Universität Dresden C++ for Scientists - Technische Universität Dresden
92 CHAPTER 4. GENERIC PROGRAMMING can trace back the error. Please try to compile this example on different compilers at your availability and see if you can make any sense out of the error messages. If you run into such lengthy error message 1 DON’T PANIC! First, look at the error itself and take out what is useful for you, e.g. missing “operator>” or something not assignable, i.e. missing “operator=” or something const that should not. Then find in the call stack your innermost code that is the part of your program where you call somebody else’s template function. Stare for a while at this and its preceding lines because this is the most likely place where the error is made. Does a type of the template function function’s argument is missing an operator or function as mentioned in the error? Do not get scared away from this, often the problem is much simpler than it seems from the never-ending error message. From our experience, most errors in template functions one can find faster than run-time errors. Another question we have not answered so far is what happens if we use two different types: unsigned u1= 2; int i= 3; std::cout ≪ ”The maximum of u1 and i is ” ≪ max(u1, i) ≪ ’\n’; The compiler tell us — this time briefly — something like Error: no match for function call ≫max(unsigned int&, int)≪ Indeed, we assumed that both types are the same. Now can we write a template function with two template parameters? Of course, we can. But that does not help us much here because we would not know what return type the function had. There are different options. First we could add a non-templated function like: int inline max (int a, int b) { return a > b ? a : b; } This can be called with mixed types and the unsigned argument would be implicitly converted into an int. But what would happen if we also add a function for unsigned? int max(unsigned a, unsigned b) { return a > b ? a : b; } Shall the int be converted into an unsigned or vice versa? The compiler does not know and will complain about this ambibuity. At any rate, adding non-templated overloads to the templated implemention is far from being elegant nor productive. So, we remove all non-templated overloads and look what we can do in the function call. We can explicitly convert one argument to the type of the other: unsigned u1= 2; int i= 3; std::cout ≪ ”The maximum of u1 and i is ” ≪ max(int(u1), i) ≪ ’\n’; Now max is called with two ints. Another option is specifying the template type explicitly in the function call: unsigned u1= 2; int i= 3; std::cout ≪ ”The maximum of u1 and i is ” ≪ max(u1, i) ≪ ’\n’; 1 The longest we have heard off was 18MB what corresponds to about 9000 pages of text.
4.2. GENERIC FUNCTIONS 93 Then the arguments are converted to int. 2 After these less pleasant details on templates one really good news: template functions perform as efficient as their non-templated counterpart! The reason is that C ++ generates new code for every type or type combination that the function is called with. Java in contrast compiles templates only once and executes them for different types by casting them to the corresponding types. This results in faster compilation and shorter executables but it is less efficient than non-templated implementations (which are already less efficient than C ++ programs). Another price we have to pay for the fast templates is that we have longer executables because of the multiple instantiations for each type (combination). However, in practice the number of a function’s instances will not be that large and it only really matters for non-inline functions with long implementations (including called template functions). Inline functions’ binary codes are at any rate inserted directly in the exutable at the location of the function call so that the impact on the executable length is the same for template and non-template functions. 4.2.1 The function accumulate TODO: An example on containers is much better than with ugly pointer arithmetic. Consider an array double a[n] which is described by its begin and end pointers a and a + n respectively. 3 We create a function for the sum of an array of doubles. The loop over the array uses pointers as was explained in Section 2.9. Figure 4.1 shows the positions of the begin pointer a and the end pointer a+n that is directly past the end of the array. a ❄ ✲ a + n Figure 4.1: An array of length n with begin and end pointers Thus, we specify the range of entries by an right-open interval of adresses. 2 For complicated reasons of compiler internals the explicit type parameter turns off argument-dependent name lookup (ADL). 3 An array and a pointer are treated in much the same way in C/C ++. So one can pass an array when a pointer is expected and it takes the address of the first entry &a[0]. a + n is for a pointer or array a and an integer n equivalent to &a[n]. ❄
- Page 42 and 43: 42 CHAPTER 2. C++ BASICS To make su
- Page 44 and 45: 44 CHAPTER 2. C++ BASICS float divi
- Page 46 and 47: 46 CHAPTER 2. C++ BASICS The first
- Page 48 and 49: 48 CHAPTER 2. C++ BASICS #ifndef at
- Page 50 and 51: 50 CHAPTER 2. C++ BASICS float A[7]
- Page 52 and 53: 52 CHAPTER 2. C++ BASICS Encapsulat
- Page 54 and 55: 54 CHAPTER 2. C++ BASICS As a pract
- Page 56 and 57: 56 CHAPTER 2. C++ BASICS A function
- Page 58 and 59: 58 CHAPTER 2. C++ BASICS Now that t
- Page 60 and 61: 60 CHAPTER 2. C++ BASICS we need sm
- Page 62 and 63: 62 CHAPTER 2. C++ BASICS 2.12 Exerc
- Page 64 and 65: 64 CHAPTER 2. C++ BASICS 2.13 Opera
- Page 66 and 67: 66 CHAPTER 3. CLASSES apply symm bl
- Page 68 and 69: 68 CHAPTER 3. CLASSES int main() {
- Page 70 and 71: 70 CHAPTER 3. CLASSES class solver
- Page 72 and 73: 72 CHAPTER 3. CLASSES • Compilers
- Page 74 and 75: 74 CHAPTER 3. CLASSES a real number
- Page 76 and 77: 76 CHAPTER 3. CLASSES } return ∗t
- Page 78 and 79: 78 CHAPTER 3. CLASSES This mechanis
- Page 80 and 81: 80 CHAPTER 3. CLASSES One could not
- Page 82 and 83: 82 CHAPTER 3. CLASSES class matrix
- Page 84 and 85: 84 CHAPTER 3. CLASSES Approach 3: R
- Page 86 and 87: 86 CHAPTER 3. CLASSES of the decrem
- Page 88 and 89: 88 CHAPTER 3. CLASSES There are two
- Page 90 and 91: 90 CHAPTER 4. GENERIC PROGRAMMING }
- Page 94 and 95: 94 CHAPTER 4. GENERIC PROGRAMMING A
- Page 96 and 97: 96 CHAPTER 4. GENERIC PROGRAMMING v
- Page 98 and 99: 98 CHAPTER 4. GENERIC PROGRAMMING c
- Page 100 and 101: 100 CHAPTER 4. GENERIC PROGRAMMING
- Page 102 and 103: 102 CHAPTER 4. GENERIC PROGRAMMING
- Page 104 and 105: 104 CHAPTER 4. GENERIC PROGRAMMING
- Page 106 and 107: 106 CHAPTER 4. GENERIC PROGRAMMING
- Page 108 and 109: 108 CHAPTER 4. GENERIC PROGRAMMING
- Page 110 and 111: 110 CHAPTER 4. GENERIC PROGRAMMING
- Page 112 and 113: 112 CHAPTER 4. GENERIC PROGRAMMING
- Page 114 and 115: 114 CHAPTER 4. GENERIC PROGRAMMING
- Page 116 and 117: 116 CHAPTER 4. GENERIC PROGRAMMING
- Page 118 and 119: 118 CHAPTER 4. GENERIC PROGRAMMING
- Page 120 and 121: 120 CHAPTER 4. GENERIC PROGRAMMING
- Page 122 and 123: 122 CHAPTER 4. GENERIC PROGRAMMING
- Page 124 and 125: 124 CHAPTER 4. GENERIC PROGRAMMING
- Page 126 and 127: 126 CHAPTER 4. GENERIC PROGRAMMING
- Page 128 and 129: 128 CHAPTER 4. GENERIC PROGRAMMING
- Page 130 and 131: 130 CHAPTER 4. GENERIC PROGRAMMING
- Page 132 and 133: 132 CHAPTER 4. GENERIC PROGRAMMING
- Page 134 and 135: 134 CHAPTER 5. META-PROGRAMMING exp
- Page 136 and 137: 136 CHAPTER 5. META-PROGRAMMING dou
- Page 138 and 139: 138 CHAPTER 5. META-PROGRAMMING We
- Page 140 and 141: 140 CHAPTER 5. META-PROGRAMMING Fir
4.2. GENERIC FUNCTIONS 93<br />
Then the arguments are converted to int. 2<br />
After these less pleasant details on templates one really good news: template functions per<strong>for</strong>m<br />
as efficient as their non-templated counterpart! The reason is that C ++ generates new code<br />
<strong>for</strong> every type or type combination that the function is called with. Java in contrast compiles<br />
templates only once and executes them <strong>for</strong> different types by casting them to the corresponding<br />
types. This results in faster compilation and shorter executables but it is less efficient than<br />
non-templated implementations (which are already less efficient than C ++ programs).<br />
Another price we have to pay <strong>for</strong> the fast templates is that we have longer executables because<br />
of the multiple instantiations <strong>for</strong> each type (combination). However, in practice the number of<br />
a function’s instances will not be that large and it only really matters <strong>for</strong> non-inline functions<br />
with long implementations (including called template functions). Inline functions’ binary codes<br />
are at any rate inserted directly in the exutable at the location of the function call so that the<br />
impact on the executable length is the same <strong>for</strong> template and non-template functions.<br />
4.2.1 The function accumulate<br />
TODO: An example on containers is much better than with ugly pointer arithmetic.<br />
Consider an array double a[n] which is described by its begin and end pointers a and a + n<br />
respectively. 3<br />
We create a function <strong>for</strong> the sum of an array of doubles. The loop over the array uses pointers<br />
as was explained in Section 2.9. Figure 4.1 shows the positions of the begin pointer a and the<br />
end pointer a+n that is directly past the end of the array.<br />
a<br />
❄<br />
✲<br />
a + n<br />
Figure 4.1: An array of length n with begin and end pointers<br />
Thus, we specify the range of entries by an right-open interval of adresses.<br />
2<br />
For complicated reasons of compiler internals the explicit type parameter turns off argument-dependent<br />
name lookup (ADL).<br />
3<br />
An array and a pointer are treated in much the same way in C/C ++. So one can pass an array when a<br />
pointer is expected and it takes the address of the first entry &a[0]. a + n is <strong>for</strong> a pointer or array a and an<br />
integer n equivalent to &a[n].<br />
❄