[Insight-developers] compile warnings in FEM code

Brad King brad.king@kitware.com
Fri, 21 Dec 2001 15:47:40 -0500 (EST)


Hi Aljaz,

> reason unknown to me MSVC compiler won't initialize the const static class
> members, unless they are referenced somewhere. Since the code inside classes
> assumes that these static members are initialized since forever (like they
> should be), very bad things start to happen if they are not for some reason.
> Defining global static references provides a workaround to this problem.

I just ran this test with MSVC 6 sp5:

-------------------
#include <iostream>

struct A
{
  A() { std::cout << "Hello, world!" << std::endl; }
  static const int i;
};

int f()
{
  std::cout << "Goodbye, world!" << std::endl;
  return 1;
}

static const A a;
const int A::i = f();

int main()
{
  return 0;
}
-------------------

It prints out the expected output, meaning that the variables are being
initialized.  Your problem is probably happening because the statics are
in a .o that has no symbols referenced.  If the .o is not referenced, it
gets left out of the build, so the initialization does not occur.  Your
reference workaround is merely serving to reference a symbol from the
object file containing the static data in the class.  The reason it
appeared to work on other compilers (like UNIX ones) is probably that you
were doing a shared build, in which case the .o is always included anyway.

There is another way to do the registration you want:

---- myFoo.h ----
struct Foo
{
  static void ClassRegister();
  static void ClassUnregister();
};

struct Foo_init
{
  Foo_init();
  ~Foo_init();
  static unsigned int Count;
};

static Foo_init Foo_initializer;

---- myFoo.cxx ----
#include "myFoo.h"

void Foo::ClassRegister()
{
  // registration code
}

void Foo::ClassUnregister()
{
  // unregistration code
}

unsigned int Foo_init::Count; // Purposely left uninitialized.

Foo_init::Foo_init()
{
  if(++Foo_init::Count == 1) { Foo::ClassRegister(); }
}
Foo_init::~Foo_init()
{
  if(--Foo_init::Count == 0) { Foo::ClassUnregister(); }
}

----------------

The idea is that the "Foo_initializer" variable in the header will count
the number of translation units that include "myFoo.h".  It also makes
sure that the .o corresponding to myFoo.cxx is linked in so that the
Foo_init constructor/destructor can be found.  The Foo_initializer
variable has a constructor, so the compiler won't warn if the variable is
not used.

Hopefully you can adapt this approach to your needs.

-Brad