views:

109

answers:

2

I'm storing expanded SVN keyword literals for .cpp files in 'static char const *const' class members and want to store the .h descriptions as similarly as possible. In short, I need to guarantee single instantiation of a static member (presumably in a .cpp file) to an auto-generated non-integer literal living in a potentially shared .h file. Unfortunately the language makes no attempt to resolve multiple instantiations resulting from assignments made outside class definitions and explicitly forbids non-integer inits inside class definitions. My best attempt (using static-wrapping internal classes) is not too dirty, but I'd really like to do better. Does anyone have a way to template the wrapper below or have an altogether superior approach?

// Foo.h: class with .h/.cpp SVN info stored and logged statically
class Foo {
  static Logger      const verLog;
  struct hInfoWrap;
public:
  static hInfoWrap   const hInfo;
  static char const *const cInfo;
};

// Would like to eliminate this per-class boilerplate.
struct Foo::hInfoWrap {
  hInfoWrapper() : text("$Id$") { }
  char const *const text;
};

...

// Foo.cpp: static inits called here
Foo::hInfoWrap  const Foo::hInfo;
char const     *const Foo::cInfo = "$Id$";
Logger          const Foo::verLog(Foo::cInfo, Foo::hInfo.text);

...

// Helper.h: output on construction, with no subsequent activity or stored fields
class Logger {
  Logger(char const *info1, char const *info2) {
    cout << info0 << endl << info1 << endl;
  }
};

Is there a way to get around the static linkage address issue for templating the hInfoWrap class on string literals? Extern char pointers assigned outside class definitions are linguistically valid but fail in essentially the same manner as direct member initializations. I get why the language shirks the whole resolution issue, but it'd be very convenient if an inverted extern member qualifier were provided, where the definition code was visible in class definitions to any caller but only actually invoked at the point of a single special declaration elsewhere.

Anyway, I digress. What's the best solution for the language we've got, template or otherwise? Thanks!

A: 

Maybe you could do something with macros.

// Foo.h
#define FOO_HINFO "$Id$"

...

// Foo.cpp
char const     *const Foo::hInfo = FOO_HINFO;

I usually avoid macros, but in this case it might be the cleanest solution.

KeithB
Since I was trying to find a solution that my peers would want to use as well, I probably would have chosen this straightforward approach instead of any of the 'purer' wrapper methods, were it not for Alsk making me realize my bigger oversight. Thank you very much for the response though!
Jeff
+1  A: 

probably, with a static function?

// Foo.h: 
class Foo {
  static Logger      const verLog;
  static char const*const getHInfo() { return "$Id$"; }
public:
  static char const *const cInfo;
};

// Foo.cpp: static inits called here
char const     *const Foo::cInfo = "$Id$";
Logger          const Foo::verLog(Foo::cInfo, Foo::getHInfo());
Alsk
I completely forget that in-class-definition static method definitions were legal. This is what I'll end up using. Thanks!
Jeff