Logical error in function template

My professor gave me this assignment.

Introduce a generic function called Max, which takes 3 arguments of a generic type and returns the maximum of these 3. Deploy a specialized function for char * types.

Here is my code:

#include <iostream> #include <string> using namespace std; template<typename T> T Max(T first,T second,T third ) { if(first > second) { if(first > third) { return first; } else { return third; } } else if(second > third) { return second; } else { return third; } } template<> char* Max(char* first,char* second,char* third) { if(strcmp(first, second) > 0) { if(strcmp(first, third) > 0) { return first; } else { return third; } } else if(strcmp(second, third) > 0) { return second; } else { return third; } } int main(void) { cout << "Greatest in 10, 20, 30 is " << Max(10, 20, 30) << endl; char a = 'A'; char b = 'B'; char c = 'C'; char Cptr = *Max(&a, &b, &c); cout << "Greatest in A, B ,C is " << Cptr << endl; string d = "A"; string e = "B"; string f = "C"; string result = *Max(&d, &e, &f); cout << "Greatest in A, B, C is " << result << endl; } 

Output:

The largest at 10, 20, 30 - 30
The greatest in A, B, C is C | The greatest in A, B, C is A

Problem:

If I pass char data types to the functions Max, A, B, C, it returns C, but if I pass the string data types A, B, C, it will return A.

Why does he return A here?

+4
source share
4 answers

There are two problems here. Two other answers already described the problem with your third call.

But your second call is also incorrect:

 char a = 'A'; char b = 'B'; char c = 'C'; char Cptr = *Max(&a, &b, &c); 

This should lead to undefined behavior, since strcmp expects a null-terminated string, but this is not what you are passing to the function. Rather, you pass it to pointers to individual char values, and strcmp has every right to strangle it. Basically, anything can happen and that your code works is a pure chance.

The proper way to cause this overload is to simply pass char s or pass C-style strings:

 char C = Max(a, b, c); // or: char as[] = "a"; char bs[] = "b"; char cd[] = "c"; char* result = Max(as, bs, cd); 

Alternatively, you can directly pass string literals.

Finally, a note about the style. The char* specialization can be greatly reduced if you cheat a bit by converting the input char* strings to the correct std::string and reusing the generic version of Max :

 template<> char* Max(char* first,char* second,char* third) { return Max(string(first), string(second), string(third)); } 

(Of course, this is probably less effective, but in most cases it can be safely ignored.)

And one more note: the assignment explicitly asked you to specialize the function template for char* so that your answer is correct. However, an alternative would be to overload the function instead of specializing it. For function templates (as opposed to class templates), this is the usual way when you no longer need template arguments:

 char* Max(char* first,char* second,char* third) { return Max(string(first), string(second), string(third)); } 

Note that the only difference is the absence of template <> before the function header.

+4
source
 string result = *Max(&d, &e, &f); 

This line is your problem. You pass a pointer to a string, so in fact it returns the highest address of the pointer.

Keep in mind that the stack grows down, so the top of the stack has the highest address. Each subsequent stack allocation (i.e., declaring a variable in this case) will trigger a lower stack address, and therefore "A" is displayed as the largest value.

If you write this:

 string result = Max(d, e, f); 

You will get the answer you expect.

+2
source

In the first case, he uses specialization of the template in the second case, the general template.

But your problem is how you call Max in the second case:

 string d = "A"; string e = "B"; string f = "C"; // you're comparing the string addresses here, not their content string result = *Max(&d, &e, &f); 

Must be:

 string d = "A"; string e = "B"; string f = "C"; string result = Max(d, e, f); 

Also, I would suggest using const pointers in the char* specialization, because since it is standing, you cannot pass anything but non-constant pointers, which is not the usual case.

+2
source

instead

string result = *Max(*&d, &e, &f)

you need

 string result = Max(d.c_str(), e.c_str(), f.c_str()) 

Note that this will work if your function accepts const char* rather than char* . If you insist on using char *, which is wrong, you will have to discard the constant

  string result = Max(const_cast<char*>(d.c_str()), const_cast<char*>(e.c_str()), const_cast<char*>(f.c_str())); 

but since you are using string s, note that you can compare them simply with == <> etc.

+1
source

All Articles