Archive for the Rant Category

MSVC bug that’s constantly getting me

Posted in C++, cpp, Rant on April 20, 2011 by Crazy Eddie

This is partially a rant and partially instructional. I’ve just gotten bitten by this compiler bug, AGAIN, and I’m a little frustrated with it because it took a good 2 hours to find (involved template instantiations and the damn compiler never showed me the actual line of code trying to instantiate the template). As is the case with most MSVC bugs, this one involves templates.

Consider this code, what is the output you’d expect?

#include <iostream>

struct base
{
  template < typename T >
  base(T const&)
  {
    std::cout << "templated constructor\n";
  }

  base(base const&)
  {
    std::cout << "copy constructor\n";
  }
  base()
  {
    std::cout << "default constructor\n";
  }
};

struct derived
  : base
{
};

int main()
{
  derived d;
  derived d2(d);
}

If you expect the construction of ‘d’ to cause “default constructor” and the construction of ‘d2’ to output “copy constructor”, you’d be absolutely right to expect that. This is supposed to be how it works. A template constructor can never be a copy constructor and the copy constructor of a derived class is supposed to defer to the *copy* constructor of the base before building its own bits. Unfortunately, though you’re right to expect this behavior, you’d be absolutely wrong about it actually happening because MSVC is stupid here.

What you’re actually going to get from that code is a call to the template constructor in base due to the copying of a derived. The MSVC compiler simply passes the derived type up the chain. When it hits a template constructor it says, “Hey, I’ve got a static type of ‘derived’ here, which matches T better than it does ‘base const&’.” BAD, MSVC, BAD!

The workaround is to write a user-defined copy constructor and explicitly perform the cast that the compiler should be doing to begin with:

struct derived
  : base
{
  derived() : base() {} // need this now too.
  derived(derived const& other) 
    : base(static_cast<base const&>(other))
  {}
};

If you can keep this workaround in memory at all times then you’ll be safe. If you’re like me and don’t instantly think of every workaround you need to insert into your code every time you’re going to run into a well-known compiler bug…you might spend more than a short period of time trying to figure out WTF called the template constructor when you know nobody did. Well, someone did….your broken compiler did.

If, like me, the compiler refuses to tell you what bit of code is calling the template (because there actually isn’t any, though it would be nice to see, “during compilation of default created copy constructor for…,” like GCC often does) you might declare a private copy constructor in anything that derives from said object and see if you get complaints about having no access rather that long tirades of template vomit leading to dead ends. I just did this and ran into a couple places where the objects I didn’t think where ever copied where being copied.

I can’t currently be bothered to find the link, but this has been posted to MS connect. They’ve known about it for a long time. It’s probably not ever going to be fixed. It’s been around at least as far back as 2005 and the above code exhibits the same problem in 2010.

Advertisements

Why I hate having to work with Visual Studio

Posted in Rant on March 10, 2011 by Crazy Eddie

The fact that the MS C++ compiler is one of the worse on the market is bad enough. Random crashes, lockups, and intellisense taking complete control while also providing next to no actual benefit…annoys me but I’m used to it. What really bothers me though is its tendency to enter the Twilight Zone.

Today reminded me of this fact yet again. For no apparent reason every editor area in the program (luckily only one instance) has begun to:

* Place the edit cursor wherever you put it whether or not there’s anything there (well past the end of lines in other words)
* Ignore arrows, backspace, delete, etc…
* Pop up some kind of window menu when I type ‘-‘.

This is the first time I’ve run into behavior this random, but I quite regularly run into a different kind of random craziness. Probably about 1-2 times a day one of the files I’m editing will randomly enter some strange mode where indentation doesn’t work and pressing ‘:’ puts you at the beginning of the line. Makes typing things out like “std::vector::iterator” more than a little annoying. Luckily simply closing the file and opening it again goes back into normal C++ mode from whatever insane mode it was previously in.