Saturday, September 20, 2008

c++->fail()

(Continuing my musings on D)
(that code actually works, try (assuming C has a method fail):
C cAry[2];

C *c = cAry;
c++->fail();
)

I got bit by several very ugly bugs in g++ 4 this week. This is about code that works in gcc 3.2, 3.4, and Visual Studio. But breaks in g++ 4.

This is because g++ 4 is more closely matching the C++ spec!

See below for the exact code.

The first problem is mixing implementations of template member functions. This might be because you need to specially handle certain types (like strings), while having a generic implementation for the standard types (int, bool, float, etc.).

The notation in pre g++ 4 is straightforward (if ugly)

returnType ClassName<SpecificType>::functionName(args) { specific implementation }

and

template<args>
returnType ClassName<args>::functionName(args) { generic implementation }


When I compile under g++ 4, I get this error:

main.cpp:16: error: too few template-parameter-lists


In the code below, line 16 is:

void Par<std::string>::fun(void)


Well, there is the template parameter! Right there! "std::string", it's string! What more do you want from me!

Here is the working code:

template<>
void Par<std::string>::fun(void)


Oh! Of course! Duh! I should of known that. The earlier code was obviously so ambiguous that only every compiler before g++ 4 could figure it out. I'm so glad they fixed that for me!

Here is the total code:

#include <cstdio>
#include <string>

template<typename>
class Par
{
protected:
int x_;

public:
Par(void) {}

virtual void fun(void);
};

void Par<std::string>::fun(void)
{
printf("String ver\n");
}

template<typename T>
void Par<T>::fun(void)
{
printf("Generic ver\n");
}

int main(int argc, char **argv)
{
Par<std::string> p1;
p1.fun();

Par<int> p2;
p2.fun();

return 0;
}

No comments: