Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Member-Function-Scoped Variable

Tags:

c++

scope

static

Consider the following code:

#include <iostream>

struct X {
    int foo() {
        // Can I get this to be an instance-specific static variable, please?
        static int i = 0;
        return i++;
    }
};

int main() {
    X a, b;
    std::cout << a.foo() << ' ';
    std::cout << b.foo() << ' ';
    std::cout << b.foo() << '\n';
    // output is: 0 1 2
    // desired output: 0 0 1
}

Is it possible to get a copy of this static variable i for each instance of X without the need to move the declaration and initialization to some far, far away headers and constructors?

The reason I want this, is because the value of this variable is only relevant within this specific function (but also specific to the instance whose member function it is), e.g., last call parameters, time of last call etc.

The class that stands behind this idea is already somewhat large and spreading the declaration and the initialization of such tiny variables that are used within one single function is getting ugly.

Update: Note that I don't want to leak memory. When an instance is destroyed, the variables associated with it should be removed as well.

Update²: Apparantly (and unfortunately) there is indeed no proper language feature with this exact semantics. While there are some workarounds, each of them introduces limitations and pitfalls when it comes to

  • placement of "function" declaration and definition
  • accessing other "real" member variables
  • overloading the "function" in a derived class
  • ...

With these implications in mind it just appears most efficient to stick with the first thing that comes to mind:

struct A {
    int j = 0;
    int i = 0;
    int foo() { return i++ + j++; }
};

rather than going for something like this:

struct B {
    int j = 0;
    std::function<int()> foo = 
        [this, i = 0]() mutable { return i++ + this->j++; };
};

or this:

struct C {
    int j;
    struct Foo {
        int i; 
        C *c;
        Foo(C *c) : i(), c(c) {}
        int operator() () { return i++ + c->j++; }
    } foo;
    C() : j(), foo(this) {}
};

or this:

struct D {
   int j = 0;
   std::map<std::string, int> i;
   int foo() { return i[__PRETTY_FUNCTION__]++ + j++; }
};

or similar.

Many thanks for your comments and answers!

like image 239
moooeeeep Avatar asked Apr 26 '13 12:04

moooeeeep


2 Answers

No, it's not possible.

Two alternative options are available to you:

  1. Make the variable a member, which is the language feature with the semantics you want;
  2. or invent a new language.

I do understand your concern, but it really only stems from your class apparently being too large. Separate its responsibilities.

like image 142
Lightness Races in Orbit Avatar answered Oct 16 '22 16:10

Lightness Races in Orbit


My turn:

struct X {
    class _foo {
        int i;
    public:
        _foo() : i(0) { }
        int operator()(void) {
            return i++;
        }
    } foo;
};

Basically, function-static variable makes the function an object (identity, state, behavior). You just don't want it to be singleton. So here it is - a class.

like image 35
Elazar Avatar answered Oct 16 '22 15:10

Elazar