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!
CodePudding user response:
getBigger("Amber", "John")
calls getBigger<const char*>
which returns which memory address is a higher number.
CodePudding user response:
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;