Template Specializations

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


EditText of this page (last edited April 27, 2009) or FindPage with title or text search