views:

588

answers:

6

Hi all,

I would like to use the tm struct as a static variable in a class. Spent a whole day reading and trying but it still can't work :( Would appreciate if someone could point out what I was doing wrong

In my class, under Public, i have declared it as:

static struct tm *dataTime;

In the main.cpp, I have tried to define and initialize it with system time temporarily to test out (actual time to be entered at runtime)

time_t rawTime;
time ( &rawTime );
tm Indice::dataTime = localtime(&rawTime);

but seems like i can't use time() outside functions.

main.cpp:28: error: expected constructor, destructor, or type conversion before ‘(’ token

How do I initialize values in a static tm of a class?

+2  A: 

You can't call functions arbitrarily outside functions. Either do the initialization in your main() function, or create a wrapper class around the tm struct with a constructor that does the initialization.

Thomas
+4  A: 

You can wrap the above in a function:

tm initTm() {
    time_t rawTime;
    ::time(&rawTime);
    return *::localtime(&rawTime);
}

tm Indice::dataTime = initTm();

To avoid possible linking problems, make the function static or put it in an unnamed namespace.

Georg Fritzsche
+1 For unnamed namespace. (Cough, not anonymous, cough)
GMan
Thanks, changed. Maybe i'll memorize most of the C++ terms one day...
Georg Fritzsche
Heh, there's too many. I'm just being silly, anonymous and unnamed mean the same thing, but not according to the standard. :| Silly committee.
GMan
+4  A: 
struct tm get_current_localtime() {
    time_t now = time(0);
    return *localtime(&now);
}

struct tm Indice::dataTime = get_current_localtime();
Chris Jester-Young
+2  A: 

Wrap the whole thing in a function, and use that to initialize your static member:

tm gettime() {
    time_t rawTime;
    time ( &rawTime );
    return localtime(&rawTime);
}

tm Indice::dataTime = gettime();

And you don’t need to (and thus shouldn’t) prefix struct usage with struct in C++: tm is enough, no struct tm needed.

Konrad Rudolph
A: 

Also note that your struct tm is a pointer to a tm struct. The return from localtime is a singleton pointer whose contents will change when you or anyone else calls localtime again.

quixoto
`localtime` returns a static instance. So, it's not thread-safe or reentrant. There's also `localtime_r` for more robustness.
Chris Jester-Young
My answer slightly compensates for it by copying its contents straight away, but still doesn't make it thread-safe by any means.
Chris Jester-Young
Didn't realize that. Updated, thanks. What a goofy pattern that is.
quixoto
A: 

Add this:

namespace {
  class Initializer {
    public:
      Initializer() { 
        time_t rawtime; time(&rawtime);
        YourClass::dataTime = localtime(&rawtime);
      }
  };
  static Initializer myinit();
}

When the object file is initialized at run-time, the constructor Initializer() is called which then sets the "global" variable dataTime as you want. Note that the anonymous namespace construction helps to prevent potential clashes for the names Initializer and myinit.

antti.huima
Does this method have any advantage over direct initializing using function mentioned above
Yogesh Arora