Here is a very simple example of function specialization in C++. I think it should work but Visual Studio’s compiler give me an ambiguity message.
template <class T> T min(T a, T b) {
if(a < b) return a;
else return b;
}
string min(string str1, string str2) {
if(str1.length() < str2.length()) return str1;
return str2;
}
void main(int argc, char* argv[])
{
int n=12, p=15;
string str1= "monsieur", str2= "bonjour" ;
cout << min(n,p) << endl;
cout << min(str1, str2) << endl;
}
In fact it says that “min(n, p) is ambigous and don’t know which function to call. It is probably a trivial problem but I haven’t figured out the problem. I tried the following headers too:
template<> string min(string str1, string str2)
and:
template<> string min<string>(string str1, string str2)
Can someone help me out?
A non-template which doesn’t require a conversion is always the better match. That is, if these were the only definitions of
min(), there would be no problem (i.e. renaming the functionminto something else would remove the ambiguity). The ambiguity is betweentemplate <typename T> T const& std::min(T const&, T const&)and you templatized version. Another fix is to remove the using declaration and explicitly qualify names from namespacestd, i.e. the following code compiles fine:Please note that the
std::stringversion of yourmin()is not a specialization but an overload! When calling the function as you did this doesn’t matter and it will choose the version as expected. However, when calling the function while explicitly specifying the template argument it will not:(*) Actually,
min<std::string>(str1, str2)is, again, ambiguous with the version from namespacestddue to argument dependent look up; if it were named differently it would call the template version.If you wanted to really specialize the function, you would write something like this:
That said, here are few random notes on the program unrelated to the ambiguity and the specialization:
main()always has to be declared to return aint. It is allowed to omit the return statement inmain()but some compilers don’t get that right. For portable code you’re best off to use a return ofintand just return0(orEXIT_SUCCESSdeclared in<stdlib.h>).constreference: copying strings isn't that expensive, especially for smallstd::strings (because contemporarystd::stringimplementations seem to use the small string optimization) but it isn't free either. If the objects are reasonably big it can be a performance problem.std::stringversion ofmin()is ill-advised because it behaves in unexpected ways.std::endlis grossly overused and does something different than most people think it does: in addition to inserting a newline character ('\n') it also flushes the std::ostream. It is the latter part which comes as a surprise and I found that it creates major performance problems quite frequently. Unless you really intend to flush the stream, just write a \n.