Yuvraj Parashar
Yuvraj Parashar

Reputation: 81

Why is std::max not working for string literals?

I am trying to find the maximum of two strings and it is giving me the correct answer in the first case (when passing std::string variables) but giving an error in the second case (when passing direct strings).

#include<bits/stdc++.h>
using namespace std;

int main()
{
    // Case 1
    string str1 = "abc", str2 = "abcd";
    cout << max(str1, str2) << endl;

    // Case 2
    cout << max("abc", "abcd") << endl;
}

Upvotes: 5

Views: 1018

Answers (2)

JeJo
JeJo

Reputation: 32797

In your second case,

std::cout << std::max("abc", "abcd") << std::endl;

they are string literals, in which "abc" has type char const [4] and "abcd" has type char const [5].

Therefore, in the function call std::max("abc", "abcd"), the std::max has to deduce

auto max(char const (&a)[4], char const (&b)[5]) {
    return a < b ? b : a;
}

This is not possible as the std::max has no function template overload, which takes different types as template arguments. Hence, the error!


Warning!

If you explicitly mention the template type const char* in std::max, this could have been compiled. This is because, for "abc" and "abcd" the type can be also be const char*s due to array to pointer decay in C++.

 std::cout << std::max<const char*>("abc", "abcd" ) << '\n';  // compiles
                      ^^^^^^^^^^^^^

In addition, the std::initializer_list overload of the std::max, in turn will deduce the above also const char* as template type:

std::cout << std::max({ "abc", "abcd" }) << '\n';   // compiles

However, you should not be doing it !

As @AlanBirtles pointed out, this can cause the undefined behavior, due to the fact that the std::max will compare the pointers of the two different arrays. The result can not be relayed and should be doing the above. Use the std::string for comparison as in your first case. Using string literals (since C++14), you can do a minimal change, and make the second case, same as first one:

#include <string>
using namespace std::string_literals;

std::cout << std::max("abc"s, "abcd"s) << '\n';

As a side note, see the followings:

Upvotes: 10

Nolan
Nolan

Reputation: 1074

The difference comes from the types.

Typical max implementation may look like this:

template <typename T>
auto max(const T &a, const T &b) {
    return a < b ? b : a;       
}

When you use max for std::string that < sign is actually overloaded. std::string::operator<() method is used to compare strings.

When you use max for const char *. < just compares pointers disregarding content of the strings.

Upvotes: 0

Related Questions