Or, how I managed to lose five hours work to a bug in Visual C++...
First template:
template < class A > class X { ... },;
Second template:
template < class B, class C > class Y { ... },;
(Partial) Specialization of X:
template < class B, class C > class X< Y < B, C > > { ... },;
Microsoft VisualCeePlusPlus 6.0 cannot compile specializations of this kind. But GnuCpp has been doing it for the last year and a half. (I know this, because that's how old my installed copy of GnuCpp is. And I tried it, and it worked.). Last I heard, MSVC++ 7.0 won't do them either, and they haven't committed to fix it for 7.1.
I was working on a program. When I write programs, and the requirements are not changing, I do them like solving math problems. Sometimes I write code for days without ever compiling it. When I finally do compile it, it usually works, except for typos. But in this case I assumed the compiler would support something it didn't actually support. I made a very big change, updating dozens of classes to bring them into line with the new design. I saved. I compiled. I discovered this error. I became very angry.
Microsoft already knows about this error: http://support.microsoft.com/support/kb/articles/Q240/8/66.ASP
It's easy enough to roll back the changes I made; what's hard is coming up with a solution that will work around this bug, even though I already came up with a solution that ought to be fine except that it doesn't work in Visual C++.
I hate bugs in other people's software.
-- EdwardKiser
Doctor, it hurts when I write code for days without ever compiling it...
Here's an even worse one:
/* attempt to pick a function at compile time */
#include <iostream>
typedef unsigned int uint;
const char * hexdigits = "0123456789ABCDEF";
void print(uint p)
{ using std::cout;
for (int j = 0; j < 8; ++j)
{ unsigned int r = p >> 28;
cout << hexdigits[r];
p <<= 4;
},
},;
void print(uint const * u, uint len)
{ using std::cout;
using std::endl;
for (unsigned int i = 0; i < len; ++i)
{ unsigned int p = *(u + len - i - 1);
print(p);
cout << " ";
},
cout << endl;
},;
struct func_and
{ inline static uint func(uint a, uint b)
{ return a & b;
},
},;
struct func_or
{ inline static uint func(uint a, uint b)
{ return a | b;
},
},;
struct func_xor
{ inline static uint func(uint a, uint b)
{ return a ^ b;
},
},;
template<class func_t>
void modify(uint * dest, uint const * src1, uint const * src2, int len)
{ uint * dest_end = dest + len;
while (dest < dest_end)
{ *dest = func_t::func(*src1, *src2);
++dest; ++src1; ++src2;
},
},;
int main(void)
{ const uint a[8] =
{ 0x01234567, 0x89ABCDEF, 0xFEDCBA98, 0x76543210,
0x00112233, 0x44556677, 0x8899AABB, 0xCCDDEEFF
},;
const uint b[8] =
{ 0xFFEEDDCC, 0xBBAA9988, 0x77665544, 0x33221100,
0x08192A3B, 0x4C5D6E7F, 0x048C159D, 0x26AE37BF
},;
uint dest[8];
print(a, 8);
print(b, 8);
modify<func_and>(dest, a, b, 8);
print(dest, 8);
modify<func_or>(dest, a, b, 8);
print(dest, 8);
modify<func_xor>(dest, a, b, 8);
print(dest, 8);
return 0;
},;
MinimalistGnuForWindows (MinGW) does this correctly using GnuCpp from the GnuCompilerCollection, but VisualCeePlusPlus generates a program which performs func_xor every time. No warnings!
This is a well-known bug. In VC++ 6 the mangled name of an instance of a function template only includes the function parameter types and not the template arguments. The linker discards apparently duplicated template instances so you end up with a single arbitrary instance of the template. The workaround is to add an optional function parameter that is based on the template argument; here you could add func_t * = 0.
I seem to be able to find the bugs in any development tool, and I find them alarmingly quickly. It can be really irritating on the job; the boss says, "Write this program!" and I write it and expose several compiler bugs. It makes me look incompetent...
When I was in college I triggered an "internal compiler error" in GCC 2.7 (then the latest version)...
-- EdwardKiser
Want my advice? Don't write CeePlusPlus if you are using VisualCeePlusPlus: it doesn't compile C++.
And don't use templates. Templates don't work. They never have and they probably never will.
Don't use templates in Visual "C++". GnuCpp handles them just fine.
7.1 is much better though.
CategoryCpp CategoryCppTemplates