1. icon for News
  2. icon for TCHOW

News

Sunday, May 26, 2013

Why, cl.exe, Why?

When compiling C++ projects (e.g. Rktcr), I use different compilers on different platforms: Microsoft's cl.exe from Visual Studio Express Edition on Windows, Apple's clang++ from XCode on OSX, and g++ from the GCC on Linux. (These also use different versions of the C++ Standard Library, for added variability.)

This is great for catching errors in my code, as I get three different sets of static checks and three sets of design decisions (for those memory bugs that "just happen to work" on one system or another). But it also means I get exposed to a fair amount of compiler (and system library) quirkiness.

Today, I'm going to talk about one of the odder bits of behavior I've seen out of cl.exe (Version 17.00.60315.1 for x86 from Visual Studio 2012 Update 2).

I ran across this a few months back, but have been lax in posting because I didn't have any sort of CSS styling set up for posting code in news.tchow.com ; a situation which I have partially rectified (no syntax highlighting or fancy line numbers; sorry).

The Code

Apologies about the spacing in this code. Blogger apparently converts tabs to single spaces. For reference, using spaces to indent code is wrong.

#include <iostream>

template< int N >
struct TrivialTemplate {
    int val;
    typedef TrivialTemplate< N > type;
};

struct NoTemplate {
    int val;
};

//Consider different types of Coord:
#if COORD==1
typedef NoTemplate Coord; //<-- (1)
#elif COORD==2
typedef TrivialTemplate< 27 > Coord; //<-- (2)
#elif COORD==3
typedef TrivialTemplate< 27 >::type Coord; //<-- (3)
#endif

struct Pt {
    union {
        Coord arr[2];
        struct {
            Coord x;
            Coord y;
        };
    };
};

int main(int, char **) {
    Pt pt;
    pt.x.val = 12;
    std::cout << pt.arr[0].val << std::endl;
    return 0;
}

This C++ code defines type Pt, which makes use of a struct wrapped in a union to allow individual coordinate access as pt.x and pt.y, and easy coordinate indexing with pt.arr[i]. (This method can be extended to allow synonyms like pt.x and pt.r and subvectors like pt.xy or pt.yz. I use it in my Vector.hpp.)

The Problem

Notice that the lines marked (1), (2), and (3) all define Coord to be the same type -- a struct with a single int as a member -- but in slightly different ways.

So, with the line marked (1), things compile fine:

c:\Users\ix\Code\rktcr>cl /nologo /EHsc /W3 /WX /DCOORD=1 weird_template.cpp
weird_template.cpp

c:\Users\ix\Code\rktcr>weird_template.exe
12

c:\Users\ix\Code\rktcr>

If I use line (2), I get some weirdness:

c:\Users\ix\Code\rktcr>cl /nologo /EHsc /W3 /WX /DCOORD=2 weird_template.cpp
weird_template.cpp
weird_template.cpp(20) : error C2621: member 'Pt::arr' of union 'Pt::<unnamed-tag>' has copy constructor
weird_template.cpp(31) : error C2039: 'arr' : is not a member of 'Pt'
        weird_template.cpp(18) : see declaration of 'Pt'
weird_template.cpp(31) : error C2228: left of '.val' must have class/struct/union

So, what happened? Well, cl.exe has (presumably) synthesized a copy constructor for Pt::arr -- which, after some typedef expansion -- is an array of TrivialTemplate< 27 >. Now, having non-trivial constructors and destructors for data in a union is problematic, because the whole point of a union is that its members overlap in memory. However, it's also odd that a copy constructor would be synthesized -- after all, TrivialTemplate< 27 > is functionally identical to NoTemplate, and no constructor was synthesized there.

Indeed, neither g++ or clang++ have any problems compiling this code.

But here's where it gets really weird. If I compile with the line marked (3) active -- that is, if we talk about TrivialTemplate< 27 > using a typedef it contains for itself, one would expect the same error.

Instead, it just works fine:

c:\Users\ix\Code\rktcr>cl /nologo /EHsc /W3 /WX /DCOORD=3 weird_template.cpp
weird_template.cpp

c:\Users\ix\Code\rktcr>weird_template.exe
12

c:\Users\ix\Code\rktcr>

So, where does that leave me? Spending time writing workarounds -- in this case, my planar map code (which uses templated classes wrapping integers to make sure it isn't going to overflow) now has a fair number of uses of the somewhat odd-looking BitsInt< N >::self.

This is certainly a lot nicer than the llvm-gcc bug that incorrectly passed unions to functions (effectively reordering function parameters). That bug led to me abandoning Apple-supplied compilers on OSX until clang was mature enough.

Saturday, May 25, 2013

Rktcr: Stylish Tree Path Select

Today, I continue to progress on Rktcr's tree select. Actually riffling through the paths feels much more natural and usable than before, with a small magnified region around the current tick and markers to indicate important path events.

The styling of the tree is also improved, with different thicknesses for different control signals. I like how this works, and something like it is likely to appear in the next demo release.

Friday, May 24, 2013

Rktcr Path Select Tree

Today, I decided to dive back into revising path select mode in Rktcr. As I mentioned before, this has been a process without a clear design answer.

However, I think I'm getting closer. Today, I worked on a tree-like view and path selection therein. This prototype doesn't yet have flashy graphics on the tree, any sort of magnification for dealing with longer paths, or the ability to do any editing of paths. However, it does give a clear impression of the relation of paths (especially their relative times).

With some markers for important events (gems, finishing), and a fair amount more graphical polish (using lines is... well, not optimal, for sure) I think this has the potential to be the new path select.

Thursday, May 23, 2013

Enlightening Work

After a slow day and a half, the C++ port of Rainbow now has enlightenment working.

The next thing to do is probably to revisit how control works, and build effects to reflect the current state of each frequency band (unclaimed, claiming, following, crashed). These will be different than the mouse-control effects, because with touches one does not know where an inactive control point lies.

Tuesday, May 21, 2013

Utilitarian Level Select

Today, I completed the last pieces of the editing levels puzzle for my C++ port of Rainbow.

The first of these was level loading and saving (which doesn't really have a screenshot representation). The second was level selection:

This is a utilitarian screen designed for use when editing levels. Tapping any level edits it, tapping a '+' spot edits a new blank level.

One final thing I might add add to the editor is some sort of zoom capability (or I could forgo editing large levels on iPhone). The downside of this is it might encourage the creation of levels with detail too small to play on one screen; and I'd rather avoid having to have zoom during play, given that the rainbow's trail is accumulated into a framebuffer.

Monday, May 20, 2013

A More Finished Editor

Today, I continued work on the level editor component of my C++ port of Rainbow. While it isn't as pretty as it could be, it now is entirely functional, and ready to build levels with.

Here's what a little test level looks like in the editor and in the game. Note that the grey box in the lower right of the game view is a button that brings up a "restart/quit" menu -- useful to have so you can get back to the editor.

All that remains is to get peon placement and load/save looped in, and then I should be able to realize my goal of being able to build Rainbow levels "on the go". (Hmm, I wonder how I can get the files back off my phone? I should make sure there's a section for that in the XCode organizer. I think there is.)

Rainbow's Mobile Editor

I've been working on a C++/OpenGL port of Rainbow for a number of reasons. The first is that I like Rainbow, and I thought it might be fun to play on iOS. The second is that there were things I wanted to add to the gameplay that would have complicated the javascript code terribly. The third is that I'd like to be able to be productive on my iPhone.

This is the beginnings of a level editor for Rainbow, running on my iPhone.

I really don't do tile-based games very often, and when I do, the levels are often specified in ASCII. (Indeed, this is what the javascript version of rainbow uses, as you can see.) So this is my first time writing a tile grid editor. So far, it seems to feel pretty good.