VERSION|0.4.7.1|SUBJECT|C++ Undefined reference with static const int|CONTENT|[h6](Why you should never initialize a static const int inside the class declaration)[/h6]
I recently ran into a weird bug that really confused me.  The code was working in VS.Net but not in g++.

These three lines illustrate the problem:

[code]void doit(const int &amp;) {}
struct Foo { static const int VALUE = 100; };
int main() { doit(Foo::VALUE); return 0; }[/code]

In g++ 3.4.x, you get a linker error &quot;undefined reference to Foo::VALUE&quot;.

If you are like me, you probably try to avoid the &quot;enum hack&quot;, especially since recent compilers now follow the C++ standard and allow you to initialize static const members of integral type inside the class itself.

However, you should know that the code above is a declaration and an initialization, [b]NOT[/b] a definition.  You must also have a definition in a .cpp file somewhere, like this:

[code]const int Foo::VALUE;[/code]

But why do I need to define it?  Can&#039;t the compiler just figure it out?

Actually, with VS.Net you must [b]not[/b] define it.  It defines it for you automatically (it&#039;s a language extension; turn off with /Za).

But why would I need to define it anyways?  Constant values don&#039;t need storage space.

If compilers were magical that would be true.  Although compilers should see the value as a compile-time constant and always inline it when they can, they are [b]not required[/b] to inline; they may insist that you have an actual object defined.

That is why g++ gives you an &quot;undefined reference&quot; error.  It was not able to inline the constant, so it needs an actual object.  There are at least three scenarios where g++ does not inline a static const int:
[html]&lt;ol&gt;
&lt;li&gt;If you try to take the address of it (this one is obvious).&lt;/li&gt;
&lt;li&gt;You pass it to a function that takes a reference.&lt;/li&gt;
&lt;li&gt;When used with the tertiary operator &lt;b&gt;? :&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;[/html][b]So the solution for g++ is to always define the static member in a .cpp file.

But the solution for VS.Net is to NEVER define the static member in a .cpp.[/b]

[b]CONFLICTING SOLUTIONS, WHAT DO I DO??!![/b]

Well, I thought about disabling language extensions, especially since I am very angry with MS for being EVIL and trying to corrupt standards.  But I&#039;ve come up with a simpler solution:

[b]Define and initialize in the .cpp file.  It always works.[/b]

And if I need to use the value sooner, resort to the &quot;enum hack&quot;.

Note: The standards committee is working on a [url=http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#454]fix[/url] for this issue.
|DATE|1142319600