0

Please refer to this question first:

How to ensure that every method of a class calls some other method first?

By overloading -> operator, we can call some function whenever -> is used. I was wondering if there is some way to figure out what function is being called as well?

Example:

struct foo{

void func1(){

}

void func2(){

}

}

struct Bar{

void someFunc(foo* f){
    f->func1();
}

}


struct Baz{

void someFunc(foo* f){
    f->func2();
}

}

In above example, Bar and Baz can call func1 and func2. One approach is that in every class we implement some code that calls a logging function informing it the method name being called.

The other approach is overloading the -> operator to call some log() function

struct LoggingFoo : private Foo {
    void log() const { }

    // Here comes the trick
    Foo const *operator -> () const { log(); return this; }
    Foo       *operator -> ()       { log(); return this; }
};

The only problem is how to pass some information to log(), so it knows what function is being called ?

EDIT:

Found this other approach:

https://www.codeproject.com/Articles/34237/A-C-Style-of-Intercepting-Functions

Rahul Iyer
  • 19,924
  • 21
  • 96
  • 190
  • 1
    This cannot be done, C++ simply doesn't work this way, on a fundamental level. Overloaded `operator->` gets called, before the target object's method, and the target object's method is not known to `operator->`, because that lies in distant future, and fundamental laws of physics are simply immutable. Furthermore, when the world is hammer everything else look like a nail. Every function in `Foo` can call this `log()`, as the first order of business. Problem solved. – Sam Varshavchik Jan 11 '23 at 03:23
  • @SamVarshavchik - That is true, but then one needs to ensure that every function is updated to include the call to log() (which is what I mentioned as a possible approach in my question), but is more maintenance than some kind of hack like overloading -> . While what you're suggesting is a good way of doing things, I want to discover other ways of doing things which require less maintenance. – Rahul Iyer Jan 11 '23 at 03:26
  • Unfortunately, C++ is many things but "less maintenance" isn't one of them. Many have tried, none have found a magic button hiding somewhere in C++ itself, that makes it possible to automatically log class method invocations, with no work whatsoever. – Sam Varshavchik Jan 11 '23 at 03:29
  • @SamVarshavchik you are right. was hoping for some way to generate code, or use a macro or some kind of hack to reduce the work... – Rahul Iyer Jan 11 '23 at 03:33
  • Also note that in C++ you will often not even use pointers to access objects (to avoid unecessary new/delete calls). So if you follow C++ guidelines your intercept will not work anyway. – Pepijn Kramer Jan 11 '23 at 04:12
  • @PepijnKramer Pointers are not required here. Indeed, using pointers *breaks* this hacky way of intercepting method calls. The whole point is to use `->` on a **non-pointer** variable. – user229044 Jan 11 '23 at 04:20
  • Anyway I have a core guideline for myself ; "Don't use tricks" they make code do surprising things that are not clear from the source code. When people see a `->` they should not expect these kind of (side) effects. Make a function that accepts a function then let that log and call the original function, it is much more explicit (and for implementation a template function might really help here). – Pepijn Kramer Jan 11 '23 at 04:53
  • Example of what I mean here : https://onlinegdb.com/ZPVgWlzng – Pepijn Kramer Jan 11 '23 at 05:31
  • This smells like a really bad design here. What exactly are you trying to accomplish with this approach? – Dúthomhas Jan 11 '23 at 05:51
  • I found this that seemed useful: https://www.codeproject.com/Articles/34237/A-C-Style-of-Intercepting-Functions Haven't fully understood this approach yet, but keeping it here since its useful. – Rahul Iyer Jan 11 '23 at 03:44

1 Answers1

2

You can't, using this technique. At the point where log() is called, the method invocation hasn't happened yet, there is no contextual information about which method will be invoked.

What is happening here is, first the operator -> is invoked, and then the func2 invocation happens. It's no different than this:

void someFunc(foo* f){
  foo *f2 = f.operator->(); // log is called here
  f2->func2();              // method is invoked here
}

log() can't log something that hasn't happened yet.

user229044
  • 232,980
  • 40
  • 330
  • 338