'Why std::string relational operator comparison result is different for a template and a function?

In the following code, both the template and the function compare two strings and return which one is bigger. However, despite the same code (definition body), the result is different. Now, it might have something to do with taking a string vs string of characters (is it a C++ bug?) - but why is there a difference for a template though?

#include <iostream>
#include <string>

std::string getBiggerStr(std::string a, std::string b);

template <class T>
T getBigger(T a, T b);

int main() {
    std::cout << "\t" << getBiggerStr("Amber", "John") << std::endl;
    std::cout << "\t" << getBigger("Amber", "John") << std::endl;

    return 0;
}

std::string getBiggerStr(std::string a, std::string b) {
    if(a > b) return a;
    return b;
}

template <class T>
T getBigger(T a, T b) {
    if(a > b) return a;
    return b;
}

result:

        John
        Amber

Why is it different? Template definition body is copy pasted from function!



Solution 1:[1]

The type of the arguments (and thus of the template parameter) in the getBigger("Amber", "John") function call is const char*. Thus, the comparison in that function just compares two pointers, which is not how to properly compare (lexicographically) two C-style strings.

In order to force the use of std::string as the argument/template type, you can append the operator ""s suffix to the literals:

using namespace std::string_literals;
int main() {
    std::cout << "\t" << getBiggerStr("Amber", "John") << std::endl;    // Automatic conversion to std::string
    std::cout << "\t" << getBigger("Amber"s, "John"s) << std::endl;     // Here, we need to explicitly specify
    return 0;
}

Alternatively, if you don't have a C++14-compliant compiler (required for the operator ""s), then you can explicitly construct two std::string objects as the arguments:

std::cout << "\t" << getBigger(std::string{ "Amber" }, std::string{ "John" }) << std::endl;

Solution 2:[2]

getBigger("Amber", "John") calls getBigger<const char*> which returns which memory address is a higher number.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 user253751