Reputation: 314
In the following CPP code, isGreater()
function does its job right for integers. However, it does not produce the correct result for strings. My initial guess was that as std:: string ::compare()
method has not been used so I created a specialized isGreater()
template method for strings and first cout
still produces output as 1. My thought is that it must compare strings alphabetically. But, I don't think so it's doing that. Second and third cout
statements provide correct output i.e. integers in comparison and strings alphabetically. What exactly is going on in isGreater()
for strings?
#include <iostream>
#include <string>
using namespace std;
template <typename T>
bool isGreater(T x1, T x2)
{
return (x1 > x2);
}
template <>
bool isGreater(string x1, string x2)
{
return (x1.compare(x2));
}
int main()
{
cout << isGreater("AAAA", "ZZZZ") << endl; //First cout
cout << isGreater(5, 10) << endl; //Second cout
string str1 = "AAA";
string str2 = "ZZZZZ";
cout << str1.compare(str2) << endl; //Third cout
return 0;
}
Upvotes: 1
Views: 111
Reputation: 409176
The problem is that isGreater("AAAA", "ZZZZ")
doesn't call your std::string
specialization. It calls the general templated function using pointers (const char*
), and you compare those pointers instead of the strings.
You need to add a specialization (or overload) taking the pointer arguments if you want to use literal strings.
As for the std::string
specialization, the std::string::compare
function doesn't return what you think it does.
It returns a "true" (non-zero) value if the strings are not equal, which could be negative (and as non-zero will be true) if x1
is smaller than x2
. Either use the standard greater than operator (which is overloaded) or check if the returned value is greater than zero:
return x1.compare(x2) > 0;
Upvotes: 4
Reputation: 11317
As indicated in other answers, you don't call the std::string specialization, as you don't have a std::string
, you have a const char []
.
The best solution is to ensure that the templated method doesn't take over from the specialization. From C++17 on, I would use if constexpr
, in C++11 and C++14, I would use std::enable_if
. (Note that I use string_view to prevent memory allocations.)
template <typename T>
bool isGreater(T x1, T x2)
{
if constexpr (std::is_convertable_v<T, std::string_view>)
std::string_view{x1}.compare(x2);
else
return (x1 > x2);
}
Old standards:
template <typename T, typename = std::enable_if<!std::is_convertable<T, std::string>::value>::type>
bool isGreater(T x1, T x2)
{
return (x1 > x2);
}
bool isGreater(string x1, string x2)
{
return (x1.compare(x2));
}
Upvotes: 1
Reputation: 313
#include <iostream>
#include <string>
using namespace std;
template <typename T>
bool isGreater(T x1, T x2)
{
return (x1 > x2);
}
bool isGreater(string x1, string x2)
{
return (x1.compare(x2));
}
int main()
{
cout << isGreater(string("AAAA"), string("ZZZZ")) << endl;
cout << isGreater(5, 10) << endl;
string str1 = "AAAA";
string str2 = "ZZZZ";
cout << str1.compare(str2) << endl;
return 0;
}
You need to type cast else it is calling template
Upvotes: 0