-2

Suppose that I have this code:

class MyClass
{
public:
   void SomeFunction()
   {
   // Find somehow if this is first, second, or third call of a function in a main loop
   // If the function is called first time create new variables that will be used just for this function call
   }
};

MyClass myClassObject;

 int main()
{
    myClassObject.SomeFunction(); // First call
    myClassObject.SomeFunction(); // Second call
    myClassObject.SomeFunction(); // Third call
}

How can I know inside function what number of call is it? Note that I will probably have 100 function calls placed in code. Also this should work in Visual Studio on Windows and Clang on Mac.

I had one workaround:

void SomeFunction(const char* indetifier = "address")
{
     CheckAddress(indetifier); // This will check if address is stored. If it is not, create variables, if it is, if addresses matches use variables that are tied to that address.
}

I tried not to assign a new string to an "indetifier" and to let it to use default string ("address"). This of course didn't worked well as compiler will optimize "indetifier", so I was thinking that maybe a solution would be to disable optimizations for that variable, but I didn't because there should be some more elegant solution.

Also one thing came on my mind, maybe I could force inline a function and then get it's address, but this also seams like bad workaround.

I could also create new classes for every call but I would like to avoid this as there will be a lot of function calls and I don't want to think 100 different names.

If there is a way to create class object only at first call this would be awesome.

I hope that you understand what I want, sorry if something is not that clear as I am beginner coder.. :D

EDIT:

I can't use static for variables in a class because software that I am developing is a plugin that could have multiple instances loaded inside host and this will probably mess up the variables. I have tested static variables and if I create for example "static int value" anywhere and write something in it in one instance of a plugin this "value" will be updated for all instances of a plugin and this is not something that I want.

Youlean
  • 43
  • 1
  • 6
  • 3
    What about `static`? – BiagioF Sep 28 '16 at 20:28
  • "I could also create new classes for every call but I would like to avoid this as there will be a lot of function calls and I don't want to think 100 different names." Agree. You don't want to do this, but if you did, you could handle it with only one name and an array or `std::vector` – user4581301 Sep 28 '16 at 20:30
  • Do you specifically want the function to know how many times it's been called, or just whether or not this is the first call? – Justin Time - Reinstate Monica Sep 28 '16 at 20:36
  • @JustinTime I want to know if it is the first call, I don't want to count them. – Youlean Sep 28 '16 at 20:42
  • @BiagioFesta This won't work. See edit. – Youlean Sep 28 '16 at 20:43
  • @Youlean Each instance of plugin should have different memory space, shouldn't it? – BiagioF Sep 28 '16 at 20:45
  • @BiagioFesta It should, but if I create for example "static int value" anywhere and write something in it in one instance of a plugin this "value" will be updated for all instances of a plugin. – Youlean Sep 28 '16 at 20:50
  • @Youlean All right then, what about a global variable which keeps counting the call of a specific function? – BiagioF Sep 28 '16 at 20:53
  • Why don't you just make the counter a non-static member of the class... ? Btw, not sure what you're talking about with function addresses; your example code calls the same function 3 times; the address of that function will be the same on every call, it doesn't provide any of the information you're looking for. – Jason C Sep 28 '16 at 20:59
  • Alternatively why not just pass 1, 2, 3 as a parameter, or otherwise have the caller maintain its own count...? – Jason C Sep 28 '16 at 21:01
  • @BiagioFesta The plugin is very complex. There will be at least 50 classes that will call another 50 functions that I need to track. This will be more work to do than to just have vector myClass; and to resize it and call pointers as I need it. Currently I am creating new object for every class and then adding unique string to identify a function call. – Youlean Sep 28 '16 at 21:01
  • @JasonC If you inline a function every call will have different memory address, but this will also increase binary size. I could pass a unique identifier myself but I would like to make it as automatic as possible... – Youlean Sep 28 '16 at 21:05
  • @Youlean If you inline a function, *some* calls *might* have a different memory address, very often they won't, and that also [depends on how you take the address](http://stackoverflow.com/a/3318346/616460). You seem to be taking a lot of questionable approaches here. Also again, why don't you just use a non-static member as a counter or have the caller do it? – Jason C Sep 28 '16 at 21:13
  • @JasonC I can't because the functions will be placed in a loop, and at first execution it will be OK, but on second it won't or I am missing something. – Youlean Sep 28 '16 at 21:20
  • 1
    @Youlean Why does calling the functions in a loop prevent you from using a non-static member for the counter / counting things in the loop? Also I see you've buried the fact that you're only interested in the *first* call in comments here, if that's the case then your example doesn't seem to show what you're trying to do at all. Go back and edit your question to ask what you're actually trying to ask. If you're just trying to get the first call then pass it a boolean that's true the first time you call it; or separate whatever out into "initialize", or use a proper raii model. – Jason C Sep 28 '16 at 21:24
  • @JasonC I don't wan't to count number of calls. For example when main functions executed second time "count" will be 3 (if we count from 0) and there will not be any function at call 3. This could work only if I pass total number of calls to a class so I can divide count number, but then also there is int overflow... – Youlean Sep 28 '16 at 21:30
  • @Youlean What the heck does "there will not be any function at call 3" even mean? You're rambling, and mixing up terminology and stuff all over the place. Please describe the problem you're actually trying to solve, *in your original post*. You're just confusing everybody, mostly because your overall approach doesn't seem right at all, and you aren't able to even accurately describe it. Good luck! – Jason C Sep 28 '16 at 21:33

4 Answers4

0

In C++ you can use the static keyword in a local variable context to create the object only once at the first call:

#include <iostream>

struct MyObject {
    MyObject() {
        std::cout << "Creating instance " << this << "\n";
    };
};

void foo() {
    static MyObject my_instance;
    std::cout << "... inside function foo ...\n";
}

int main(int argc, const char *argv[]) {
    std::cout << "About to call foo...\n";
    foo();
    std::cout << "... second call ...\n";
    foo();
    std::cout << "... third call ...\n";
    foo();
    return 0;
}

With the above code you will notice that only on object MyObject will be created, on the first call to foo.

Note that if your function is a template then for each instantiation of the template you will get another distinct static variable. For example with:

template<int N>
void foo() {
    static MyObject my_instance;
    std::cout << "... inside function foo ...\n";
}

the all the calls to foo<1>() will use the same variable but calling instead foo<2>() will access another copy of the function (another instantiation of the function template), that will have its own distinct static variable created on the first call to foo<2>(). All static variables that have been initialized will be destroyed after the end of main when the program terminates.

6502
  • 112,025
  • 15
  • 165
  • 265
0
void SomeFunction()
{
// Find somehow if this is first, second, or third call of a function in a main loop
// If the function is called first time create new variables that will be used just for this function call
}

If the first call is to be tracked per object, then you need a member variable that keeps track of how many times SomeFuntion has been called for that object.

If the first call is to be tracked independent of objects, then you can use a static function variable that keeps track of how many times SomeFuntion has been called for that object.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
0

I can't use static for variables in a class because software that I am developing is a plugin that could have multiple instances loaded inside host and this will probably mess up the variables. I have tested static variables and if I create for example "static int value" anywhere and write something in it in one instance of a plugin this "value" will be updated for all instances of a plugin and this is not something that I want.

So make a non-static counter?

class MyClass {
   int count;
public:
   MyClass () : count(0) { }
   void SomeFunction () {
       ++ count;
       // do stuff with 'count'
   }
};

MyClass myClassObject;

int main () {
    myClassObject.SomeFunction(); // First call
    myClassObject.SomeFunction(); // Second call
    myClassObject.SomeFunction(); // Third call
}

Or just pass it as a parameter...

class MyClass {
public:
   void SomeFunction (int count) {
       // do stuff with 'count'
   }
};

MyClass myClassObject;

int main () {
    myClassObject.SomeFunction(1); // First call
    myClassObject.SomeFunction(2); // Second call
    myClassObject.SomeFunction(3); // Third call
}

But I'm really wondering what you're actually trying to do, and I highly suggest sitting back and rethinking this whole thing, because there are a number of red flags / confusing points here...

Jason C
  • 38,729
  • 14
  • 126
  • 182
0

If you're only interested in checking whether it's the first call, you can add a bool SomeFunction_first_call; to the MyClass, to act as a flag. The constructor sets the bool to true. MyClass::SomeFunction() uses the conditional check if (SomeFunction_first_call) /* ... */ to determine whether it's the first call, as follows:

class MyClass
{
    bool SomeFunction_first_call;

public:
    MyClass() : SomeFunction_first_call(true) {}

    void SomeFunction()
    {
        if (SomeFunction_first_call)
        {
            // This code only executes on first call.
            do_something();

            // Successfully handled first call, set flag to false.
            SomeFunction_first_call = false;
        }

        // This code always executes.
        do_something();
    }
};

Similarly, if you're only concerned about the first HOWEVER_MANY_CALLS calls, where HOWEVER_MANY_CALLS is a number, you can use something like this:

#include <cstdint>

class MyClass
{
     uint8_t SomeFunction_calls;

public:
    MyClass() : SomeFunction_calls(0) {}

    void SomeFunction()
    {
        // This segment will be executed until (SomeFunction_calls == HOWEVER_MANY_CALLS).
        // After this, the segment will be skipped, and the counter will no longer increment.
        if (SomeFunction_calls < HOWEVER_MANY_CALLS)
        {
            // This code only executes on first HOWEVER_MANY_CALLS calls.
            do_something();

            // Increment counter.
            ++SomeFunction_calls;
        }

        // This code always executes.
        do_something();
    }
};

Make sure to use the appropriately signed variable for the number of calls that need special handling (i.e. uint8_t for 0..255, uint16_t for 256..65,535, etc.). If different instances of MyClass will need to keep track of a different number of calls, then use a non-type template parameter to indicate this, and optionally, a defaulted typename to indicate what type the counter should be.

#include <cstdint>

template<uint64_t N, typename T = uint64_t>
class MyClass {
    T SomeFunction_calls;

    ...

    void SomeFunction()
    {
        if (SomeFunction_calls < N) {
            ...
        }

        ...
    }
};

In this case, a MyClass<4> will have special treatment for the first 4 calls to SomeFunction(), a MyClass<4444444444444444444> will have special treatment for the first 4,444,444,444,444,444,444 calls, and so on. The counter will default to uint64_t, as that should be large enough to hold the value; when only a smaller number of calls need special treatment, you can specify a smaller type, such as MyClass<4, uint8_t> or MyClass<444444444, uint32_t>.