Dave M.
Dave M.

Reputation: 1537

Is it possible to have a static portion of an automatic variable in C++?

I would like to have piece of static memory associated with an automatic variable, like this:

#include <iostream>
using namespace std;

class StaticFriend {
  public:
    /**/         StaticFriend( void ) { }
} ;

class C {
  public:
    /**/         C( StaticFriend &f ) : myFriend( f ) { }
  private:
    StaticFriend &myFriend;
} ;

int
main( int argc, char **argv, char **envp )
{
    static StaticFriend  a;
    C                    aa( a );

    cout << "hello, world" << endl;

    static StaticFriend  b;
    C                    bb( b );

    cout << "goodbye, world" << endl;

    return 0;
}

The idea is that each automatic C (aa, bb) would have an associated StaticFriend that would be initialized once and then be able to store information between lifecycles of the corresponding C. So in the example, there are two Cs (aa and bb) and each one has its own StaticFriend.

Other than having a separate StaticFriend as I've shown in my example, is there any way to accomplish this? (I do not want a single static variable in the class...more like a single static variable in each class instance.)

My use case is for logging using boost::log. I'm still trying to figure out the best way to use it, but it looks like the way filtering works, you start a log event with open_record (creating an automatic variable at the point of use), and if the severity or whatever is such that the record won't be emitted, no further activity happens on that log event. But I would like to count the number of times through and collect timing statistics on the event, even it it doesn't get logged. So I figure if my log event can tickle a static before deciding whether to continue, the static can record the minimal information I want.

Upvotes: 1

Views: 49

Answers (1)

Dave M.
Dave M.

Reputation: 1537

A preprocessor hack way of doing it (with a bit of added code to show what is possible with the StaticFriend.

#include <iostream>
#include <string>
using namespace std;

class StaticFriend {
  public:
    /**/         StaticFriend( const char *w )
                   : where( w ), count( 0 )
                   {
                       cout << "create a StaticFriend at 0x" << hex << (unsigned long)this << endl;
                   }
    /**/        ~StaticFriend( void )
                   {
                       cout << "Automatic variable " << where << " came into scope " << count << " times" << endl;
                   }
    void         tickle( void ) { ++count; }

  private:
    string       where;
    unsigned     count;
} ;

class C {
  public:
    /**/         C( StaticFriend &f )
                   : myFriend( f )
                   {
                       cout << " C@0x" << hex << (unsigned long)this << " has StaticFriend at " << (unsigned long)(&myFriend) << endl;
                       myFriend.tickle( );
                   }

    /**/        ~C( void )
                   {
                       cout << "~C@0x" << hex << (unsigned long)this << endl;
                   }

  private:
    StaticFriend &myFriend;
} ;

#define str_(x) #x
#define str(x) str_(x)
#define autoC( name, ... ) static StaticFriend name##_(#name " at " __FILE__ ":" str(__LINE__)); C name( name##_ ##__VA_ARGS__ )

int
recurse( int depth )
{
    autoC( x );

    cout << "recurse( " << depth << ")" << endl;

    if (depth > 0) recurse( depth - 1 );
}

int
main( int argc, char **argv, char **envp )
{
    cout << "Hello, world" << endl;

    recurse( 3 );

    cout << "Goodbye, world" << endl;

    return 0;
}

Output:

$ ./test
Hello, world
create a StaticFriend at 0x562fae948200
 C@0x7ffe6bab9ea8 has StaticFriend at 562fae948200
recurse( 3)
 C@0x7ffe6bab9e68 has StaticFriend at 562fae948200
recurse( 2)
 C@0x7ffe6bab9e28 has StaticFriend at 562fae948200
recurse( 1)
 C@0x7ffe6bab9de8 has StaticFriend at 562fae948200
recurse( 0)
~C@0x7ffe6bab9de8
~C@0x7ffe6bab9e28
~C@0x7ffe6bab9e68
~C@0x7ffe6bab9ea8
Goodbye, world
Automatic variable x at test.cc:51 came into scope 4 times

Upvotes: 1

Related Questions