Fuck You GCC!

Yesterday I spent several hours trying figure out why g++ couldn’t resolve a set of nested templates. I figured it was a strange problem with how C++ worked. It didn’t make any sense to me because I could see how the templates should be resolved. I just couldn’t figure out why it wasn’t working. It certainly looked like inheritance was screwing up the template resolution. (This is the code.) I emailed John the code, and he didn’t have any problems compiling it. That’s when I realized, it’s a fucking compiler bug in g++ 4.1.2.

fuckyou-cpp.cpp: In function ‘void serialize(std::ofstream&, std::vector >*) [with V = std::basic_string, std::allocator >]’:
fuckyou-cpp.cpp:100: instantiated from here
fuckyou-cpp.cpp:18: error: no matching function for call to ‘serialize(std::basic_ofstream
>&, std::basic_string, std::allocator >*)’
fuckyou-cpp.cpp: In function ‘void unserialize(std::ifstream&, std::vector >*) [with V = std::basic_string, std::allocator >]’:
fuckyou-cpp.cpp:114: instantiated from here
fuckyou-cpp.cpp:38: error: no matching function for call to ‘unserialize(std::basic_ifstream
>&, std::basic_string, std::allocator >*)’

Update: Sat May 10 19:04:30 PDT 2008
So after much tribulations, I thought I figured out how g++ resolved templates. In fact, I thought I figured it out, right up until the moment I tested my theory. Then it worked. Then I intentionally tried to break the code, and it still worked. Damn it. I thought I learned something, only for it turn out that I didn’t learn anything. I learned all about -frepo (and how it can cause an infinite loop in some versions of g++), #pragma implementation and #pragma declaration, and -fno-implicit-templates (and how it works on the entire file, thus breaking STL code), and even different template resolution methods.

Now the code I wrote works without any of those switches, and without shoving explicit declarations in a separate file. I have no idea why. I asked Arek to test it on a newer version of g++, and he said that my fuckyou-cpp.cpp didn’t work on anything newer. But he did mention that he got it to work by just flipping the order of template declarations.

So I guess these are the lessons:

  1. Make sure you put the vaguest template declaration first.
  2. If you need an untemplated version (i.e. the template is fully specified), then put that in a cpp file separate from the hpp file that will be included in the other files. If you don’t you’ll get multiple declarations of the untemplated version since it’s now contained in multiple files.