Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Logical error in Function template

My professor has given me this assignment.

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

Here's 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 :

Greatest in 10, 20, 30 is 30
Greatest in A, B ,C is C
Greatest in A, B, C is A

Problem :

If I pass char datatypes in Max function A, B, C, it returns C, but if I pass string datatypes A, B, C it returns A.

Why does it return A here?

like image 246
Searock Avatar asked Jan 22 '23 07:01

Searock


1 Answers

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

But your second call is also wrong:

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

This should produce undefined behaviour since strcmp expects zero-terminated strings but this isn’t what you feed into the function. Rather, you are passing it pointers to individual char values and strcmp has every right to choke on this. Basically, anything can happen and that your code works is pure chance.

The right way to call this overload would be just to pass chars, or to 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 could pass the string literals directly.

Finally, a note on style. You char* specialization can be shortened considerably if you “cheat” a little bit by converting the incoming char* strings to proper std::strings and re-using the generic version of Max:

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

(Granted, this probably is less efficient but in most cases this can be safely ignored.)

And yet another remark: the assignment explicitly asked you to specialize the function template for char* so 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 don’t require more 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 missing template <> in front of the function header.

like image 90
Konrad Rudolph Avatar answered Jan 30 '23 05:01

Konrad Rudolph