Fast, Easy, Cheap: Pick One

Just some other blog about computers and programming

While We're Talking C++...

Damn, I just read Anton’s blog post (see PlanetCJP) and it made me feel geeked out. I remember dealing with those same VC6 issues a few years ago. I’m fortunate enough to be programming under VC7.something (.Net 2003) here so I can avoid most of these issues. Also I never have to touch MFC, which is also nice, because I loathe it :)

While we’re on the topic of annoying compiler bugs, I found this one today which I think is a problem with VC7’s interpretation of the code, because I believe it’s valid.

Lets say I define a priority queue as so:

struct EdgePriorityComp { const Graph& G; EdgePriorityComp(const Graph& G) : G(G) {}; bool operator()(const Edge e1, const Edge e2) const; }; typedef std::priority_queue<Edge, std::vector<Edge>, EdgePriorityComp> EdgePriorityQueue;

The details of the types used there aren’t entirely important, but lets just say that the edges belong to a graph and have a custom ordering where you can’t simply use Less for the purpose as in a simple priority queue.

Then when attempting to instantiate this with a graph instance I wrote:

Graph myGraph; EdgePrioritytQueue myQueue(EdgePriorityComp(myGraph));

The problem is that for some reason VC7 interprets the segment:

EdgePriorityComp(myGraph)

as an anonymous function declaration instead of a temporary instantiation of an EdgePriorityComp object. However, VC7 only issues a warning and not an error. Since my project usually dumps a bunch of warnings (not my fault, from the framework I’m using!) they’re fairly easy to miss. Nothing was happening as I expected and it took me quite some time to track down the specific problem. Fortunately this was the only block of code I was working on today so the search was at least somewhat isolated.

To get it to work you need to code something like this:

Graph myGraph; EdgePriorityComp myComp(myGraph); EdgePrioritytQueue myQueue(myComp);

Now, I know this is typical an issue when you try to call a default constructor with something like

Foo myFooInstance();

which is actually equivalent to declaring a local function as such:

Foo myFooInstance(void);

instead of calling the default constructor. I was not aware that the same thing was true for non-default constructors, especially when the statement is being used as a parameter for another function call!

Ok, well, there’s my programming related problem rambling for now, hopefully this will disuade anyone from blogging about programming ever again, just in case they set me off once more.