Gotcha No. 1
This article will present some compiler dependent features of the C++ language, ie. how the arguments are interpreted in a template function, and how the type of the parameters is deducted based on the passed information to the function and of course, what does the C++ standard say.
Take the following program (I took it from a great book, "C++ Templates, the Complete Guide"):
#include <typeinfo>
#include <iostream>
template <typename T>
void ref (T const & x)
{
std::cout << "x in ref(T const&): " << typeid(x).name() << '\n';
}
template <typename T>
void nonref (T x)
{
std::cout << "x in nonref(T): " << typeid(x).name() << '\n';
}
int main()
{
ref("hello");
nonref("hello");
}
Compile it with a compiler that supports the newly introduced typeinfo. Some older compilers do not support it. What do you think it will print? Don’t bother too much:
x in ref(T const&): char const [6]
x in nonref(T): char const *
This is correct. Or at least, this is how the things are supposed to work…
The reason: during argument deduction in templates if there are references used, while calling the templated function with an array of characters (string literal), the decent C++ compiler will interpret it as an array, but if no reference is used, then the argument will be interpreted as a simple pointer to char.
During the test I have found that MS Visual C++ 2003 and MSVCExpress 2005 are producing this kind of output.
There are some differences how the const-ness is interpreted, the tendence is that older compilers omit the consts.
But I have met some compilers (for example the older BC55 which still requires the older variant of iostream.h , and Borland Cbuilder 6), which have produced the following output:
x in ref(T const&): char *
x in nonref(T): char *
This is quite acceptable, if we don't really stuck to the constness of things and if we don't really care if the things we are working on are char-pointers or arrays, but GCC (3.4.2, which comes with CodeBlocks or DevCPP) really scared the hell out of me:
x in ref(T const&): A6_c
x in nonref(T): PKc
Now what was I supposed to do with this… Of course, this is definitely can be interpreted as a valid typeinfo (A6_c could mean: Array 6 of characters, and PKc could mean Pointer constant to characters... but for this I had to use my intuition... But in this case the result was quite nice).
For my relevation, the Digital Mars compiler (8.49) somehow corrected the above by providing human readable types:
x in ref(T const&): char const *
x in nonref(T): char const *
Of course, this one forgot about the array too but at least the result it gave back was human-readable. And I was very pleased with the presence of the consts. But I was somehow disapointed, that I had to modify my source file… I had to remove the std:: from front of cout… and indeed, when I looked into the header files, I've found that Digital Mars did not include the definition of the cout in the standard namespace. Don't ask me why…
So, as you can see things really can vary so be careful when choosing a compiler.
Compilers tested:
Microsoft Visual C++ 2003
Microsoft Visual C++ 2005 Express
Borland C++ 5.5
Borland CBuilder 6
Digital Mars 8.49
GCC 3.4.2
(c) 2007 fritzone