Something Very Special

by Tim
Mon, September 28, 2009 -- 17:34 CDT

The following is a fairly technical post about something that came up during our programming efforts. It assumes a certain amount of experience with the intricacies of C++, so if that’s not your cup of tea, don’t pay this post any mind.

I spent some time yesterday integrating my C++ math library with Lua. I have a pretty robust Lua integration library at this point, but it heavily leverages template partial specialization to achieve the ease-of-extensibility that I want. While I have become rather adept in the past few months at dissecting and making use of template error messages, I ran into a confounding error that I simply had to share*.

Here is a C++ program that represents the kind of task I was attempting to implement. The original code was implementing C++-side templated generation of Lua userdata metatables for my templated mathematical primitive classes. The following code snippet, while contrived, should serve as a more digestible demonstrative example.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
using namespace std;
 
// A few generic templates
template <int N>
struct Foo
{
};
template <>
struct Foo<1>
{
};
template <int N>
struct Printer
{
  static void Print()
  {
    cout<< "You have " << N << " " << Texter<Foo<N> >::GetText() <<endl;
  }
};
template <typename T>
struct Texter
{
  static const char* GetText() { return "apples"; }
};
 
// Let's call this next specialization "A"
template <>
struct Printer<1>
{
  static void Print()
  {
    cout<< "You have just one " << Texter<Foo<1> >::GetText() <<endl;
  }
};
 
// And let's call this next specialization "B"
template <int N>
struct Texter<Foo<N> >
{
  static void Test() { Printer<N>::Print(); }
  static const char* GetText() { return "apple"; }
};
 
int main(int argc, char** argv)
{
  Texter<Foo<1> >::Test();
}

So, what would you expect to happen when you run this program? I would have expected it to print out, “You have just one apple” and terminate. What I would NOT have expected is for it to spit out this error:

1
2
3
4
5
6
7
8
9
10
11
12
1>------ Build started: Project: TrickyTemplates, Configuration: Debug Win32 ------
1>Compiling...
1>main.cpp
1>c:\finalformgames\trickytemplates\trickytemplates\main.cpp(40) : error C2039: 'Test' : is not a member of 'Texter<T>'
1>        with
1>        [
1>            T=Foo<1>
1>        ]
1>c:\finalformgames\trickytemplates\trickytemplates\main.cpp(40) : error C3861: 'Test': identifier not found
1>Build log was saved at "file://c:\FinalFormGames\TrickyTemplates\TrickyTemplates\Debug\BuildLog.htm"
1>TrickyTemplates - 2 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

It was telling me that Texter<Foo<1>> does not have a method named Test in it. But there Test is, right above the call to it! All my efforts to statically analyze the program for the problem were fruitless (in part because the actual code was vastly more complex than this example). So, I did what anyone would do in my shoes, and started poking at it with a stick.

One surprising result: if I changed Printer to take in an additional template parameter, typename T, the error went away.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
template <typename T, int N>
struct Printer
{
  static void Print()
  {
    cout<< "You have " << N << " " << Texter<Foo<N> >::GetText() <<endl;
  }
};
...
template <typename T>
struct Printer<T, 1>
{
  static void Print()
  {
    cout<< "You have just one " << Texter<Foo<1> >::GetText() <<endl;
  }
};
...

Well, that’s pretty strange. Needless to say, this did little to allay my worry.

So, I rolled it back and broke out an old tried-and-true technique I picked up while working with the Metrowerks Codewarrior debugger: try moving blocks of code around. Sometimes this is illuminating, and, in fact, I found that by swapping the order of specializations “A” and “B” (see above code snippets), the error went away. Again, not too reassuring, but it gave me a lead by suggesting that something about this bug must relate to the order in which things are defined.

I searched online for all manner of permutations of keywords relating to the situation, and finally found this post on a site about the programming language D (which has many similarities to C++):

“If two template specialization refer to each other, there is the possibility that one of them will try to instance the other before the specialization for the other is created. The result would be either a compile error or an attempt to instance the wrong template. On the other hand, if I’m not missing something, a compiler would also be correct to lazy evaluate specializations, in which case this problem may well not occur. Some way to ensure the desired behavior here would be needed.”

So, my current understanding as to what was going on is as follows: The Printer<1> specialization is instantiating the Texter<Foo<1>> specialization before the Texter<Foo<N>> specialization is defined. This is because the correct order cannot be determined due to two specializations cyclically referring to each other. As a result, it is masking out the later definition of the Texter<Foo<N>> specialization. When we call Texter<Foo<1>>::Test() in main(), it uses the incorrect specialization, which does not define the a member named Test. This may be inaccurate, but it seems to line up best with the symptoms from what I have figured out. That being said, if you are familiar with this bug, or have a contrasting theory, please share with us below in the comments.

What’s especially surprising about this error is that there is supposed to be an error message you get when it happens! It’s not hard to invoke it, either:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// This compiles just fine:
template <int N> struct X
{
  static void A() { Y<N>::B(); }
  static void C() { }
};
template <int N> struct Y
{
  static void B() { X<N>::C(); }
};
int main(int argc, char** argv)
{
  X<1>::A();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// This, however, throws a C2908!
template <int N> struct X {};
template <int N> struct Y {};
template <>
struct X<1>
{
  static void A() { Y<1>::B(); }
  static void C() { }
};
template <>
struct Y<1>
{
  static void B() { X<1>::C(); }
};
int main(int argc, char** argv)
{
  X<1>::A();
}

I do not mean to fault Microsoft for their failure to throw this error at me. It’s one hell of an edge case, and if you’re in this deep, you really ought not to rely on your compiler to bail you out when you do Bad Things. That being said, it’s nice to be able to trust that your compiler is Always Right, and experiences like this make that trust feel tenuous and uncertain.

In conclusion, do not let your template specializations refer to each other cyclically, or you may find yourself a sad, sad panda.

*Please note that this post refers specifically to behavior I experienced using Visual Studio 2008 9.0.21022.8 RTM on a machine running Windows XP. If you are on a different platform, you may or may not experience the same behavior.


Business Time (Part II)

by Tim
Fri, August 28, 2009 -- 18:16 CDT

This is the second installment of what I suspect will become a weekly series of articles on our adventures in starting our own company. If you haven’t read the last one, you might want to check it out here. Today’s topic is: The Partnership Agreement.

As you most likely know, incorporating is all about creating a collective legal body that represents your business, which can be convenient for a number of reasons. For one, this entity can acquire and own property, and can transfer it to other people. Secondly, it can represent a sort of a firewall against debt and lawsuits; a straw man that will burn in effigy for your mistakes. Lastly, it is immortal, in that it endures even when those that created it have passed on. You may have noticed that some of these qualities are shared by golems, robots, voodoo zombies, and Giant Robo. This is because they, too, are mindless automatons that possess no soul of their own*. They are surrogates that can only be operated by proxy.

You and your corporation!

You and your corporation!

When you incorporate, you are given your very own legal entity that you can use to do business with the world at large. The tricky question is who gets to control it, and under what circumstances. The answer lies in the Partnership Agreement, which is the subject of today’s post. When you found the company, you establish a contractual set of rules that govern the inner-workings of the corporation. These rules must be arrived-upon in advance, to resolve any number of hypothetical future disasters. Some examples of the kinds of questions the partnership agreement should attempt to answer:

  • When making major decisions, how should they be decided? An executive decision-maker? A vote? Consensus?
  • What happens when a new parter joins the company?
  • When the company makes money, who gets it, and how much?
  • Who decides what the company does and doesn’t spend its money on?
  • If someone puts more money in, should they get more money out, or get their money back first?
  • If someone leaves the company, do they get to take their contributions with them?
  • If someone dies or becomes permanently disabled, what happens to their share in the company?
  • What happens if someone stops showing up to work, or gets another job?
  • Involuntary termination: What happens if someone starts stealing from the company, commits a felony, goes insane (like, clinically insane)?
  • If a third party wants to buy someone’s share in the company, is that allowed?
  • If the sale is allowed, does that person become a decision-maker, or just a money-maker?

It took us a while to come to agreement on the answers that best matched our vision of the company. In particular, we opted for decision-by-consensus for all major decisions, such as bringing on a new partner, selling the company, etc… We also decided on an even-split on profits, with equal initial investment. Suffice to say, you will want to find a lawyer with whom you can discuss the best solutions people have found to answering these questions. The implications of these decisions are very serious, and there are some popular answers that do not play nice with consensus-run organizations.

It was interesting, having the three of us and our lawyer in a room, talking about the various common nightmare scenarios that come up when you set out to share decision-making power with other human beings whose vision, needs, and goals can never fully line up with your own. Looking around the room, you must force yourself to imagine how those that you most trust might some day be standing on the other side of a line you drew together in the sand. I imagine that this is similar to what it feels like to draft a pre-nuptial agreement. It was sobering, and it is my hope that I will never come face-to-face with the scenarios we so carefully shielded ourselves against in that document. Still, one cannot help but wonder what a post like this looks like when you return to it years later.

After a few serious meetings, we arrived at answers we were willing to stand by, with our lawyer taking on the task of drafting it into a legal document. It took a while to figure it all out, but there’s clearly a great deal of value in coming to an up-front legal agreement regarding your basic management and ownership assumptions. Going through this process showed us that there are a number of problems that are very hard to resolve if you do not decide on the answers to them in advance. That’s it for this installment, check in next week for Part III!

* = Except for Robo, who posesses a soul and learned long ago how to love.


Business Time (Part I)

by Tim
Wed, August 19, 2009 -- 14:59 CDT

Well, here we are, our webpage is finally live. It’s taken longer than expected getting from “let’s start this party!” to “man, this is a sweet party!”, so I thought it might be interesting to share some of the unexpected hurdles we’ve bumped into along the way. Particularly, those pertaining to Starting A Business. When I inquired with friends who had trod this path before me, they shared their Great Lessons – sage words of wisdom earned at a great cost. Unfortunately, because I did not at the time possess a clear outline of the overall shape of what was to come, these bits of widsom were of little immediate value to me. I hoped that some day they would become useful, like in the movies when a bullet is stopped by a seemingly-worthless trinket the main character keeps on a chain around his neck.

Given our lack of clarity on the issue, and because we happen to work in an office teeming with talented lawyers, the first thing we did when we hit the ground was find a lawyer and start talking about exactly what steps must be taken to start a game development business in Philadelphia. It turns out it is at once easier and more difficult than we had imagined. Let’s start with the easy part: First we needed to decide what kind of corporation we wanted. There were several options on the table, but we quickly whittled it down to either an LLC or S-Corp. The differences between the two are subtle, and we talked for a while about the tax and liability implications. Because it is such a complex optimization space, it’s hard to confidently recommend anything to anyone. That being said, we decided on an LLC for now, with the option for an S-Corp election if and when we establish some cash flow. This seemed right for a situation where all partners are supporting themselves out-of-pocket, startup costs are low, and losses are expected for at least the first year.

The next question was where we should incorporate. Apparently, there is something of a mythos surrounding ‘Delaware Corporations‘, a mark of priviledge and prestige in the business world. Companies sometimes even append it like a title, e.g. “Columbian Chemicals Company (a Delaware Corporation)”. According to our friends in the business world, this made a lot of sense a few decades ago because of Delaware’s tax incentives. However, as time went on, other states figured out why everyone was incorporating in Delaware. Hungry for that tax revenue, they adopted competetive incentives, and the free market corrected itself. So, given that there was no obvious advantage to incorporating out-of-state, and the massive headache of dealing with twice as many state tax bureaus, we decided to go with Pennsylvania after all.

delaware

Delaware. Where the corporations come from.

A quick aside – apparently, Philadelphia is working with a group called the Videogame Growth Initiative to establish incentives for incoming game developers and publishers. Given that Philly recently decided to join California for an old-fashioned budget crisis, it seems unlikely that any such investments are likely to pass in the short-term. Still, it suggests that such incentives are starting to crop up in less-well-known locations, and that video game startups may actually do well to look outside of CA when deciding where to set up shop.

But enough about Philly. Once we finished officially incorporating (there is a form and a fee) and received our tax ID (which is like the SSN of a business), we were able to set up our company bank account. Each of us poured an equal part to cover startup costs (office equipment, software, hardware, etc…), and we all got fancy-looking bank cards. In this process, I learned an amusing fact: when bankers hear that you are starting a business, they get Excited. Coming from a world of personal finance limited to free checking that comes with a free casserole dish, it was jarring to see the curtain pulled back, and realize how much more interested banks are in ‘helping you out’ when you are talking about a business account. And by helping you out, of course, I mean selling you services that make no sense for a tiny three-man company. So, we thanked them for their enthusiasm and promised we would talk more if/when we see a positive number on our balance sheet.

Anyways, That just about wraps up this first installment. I’d love to hear any other indie devs’ experience with this – the comment section awaits you! Next time: The Hard Part.