Sunday, September 21, 2008

The Horror, the Horror

(Continuing my rant on g++ 4, which is a part of my musings on D)

Ok, take the code from last time, and add this after the "class Par" definition:

template<typename T>
class Child : public Par<T>
{
public:
void fun(void)
{
x_ = 4;
}
};
This code should compile on on gcc 3.4 or in Visual Studio. g++ 4 gives the following error:

main.cpp: In member function 'void Child::fun()':
main.cpp:22: error: 'x_' was not declared in this scope

Err, excuse me! x_ is inherited from the parent. Just look, it's 'int x_'. It's protected, that means it's visible to any children! How can I fix this! I don't know what to do!

After about five minutes of careful Googling, I found a site that seems to understand what's going on. They say:
"The C++ standard prescribes that all names that are not dependent on template parameters are bound to their present definitions when parsing a template function or class."
There is actually a good reason behind this. People were having problems where templates were full of buggy code, but no one knew it until you tried to use them (because the compilers were just turning off error checking when interpreting template code). So now, compilers are trying to understand the template code, and check it for errors. The only problem is good code is now wrongly flagged as erroneous code. Oops!

There is a fix:
this->x_ = 4;

Ok, I can see how that helps the compiler figure stuff out. However, it hurts my brain... If somebody else sees this code (and isn't familiar with this change in the compiler, like say they've been programming C++ for the last ten years and never seen it - like I was until this week) they are going to say, "Oh, that 'this' isn't needed. I'll just remove it." Let's say it's in some utility header (like a good template should be). And that it takes an hour to recompile (like my project does). And they change a lot of other stuff before starting a full recompile (because you don't want to wait an hour between every one line change). And then they get that bizarro error. Yea, they're gonna be mad. And they're going to have to back track through all the changes they've made, google for the page above (assuming they can find it, I only found it by looking for "two stage name lookup" - yea, that's intuitive), and recompile another hour or two.

Enjoy! :..(

Note: apparently, it went into g++ 3.4, only 3.2 is safe!

No comments: