tags:

views:

185

answers:

6

I have a C++ class I want to inspect. So, I would like to all methods print their parameters and the return, just before getting out.

The latter looks somewhat easy. If I do return() for everything, a macro

#define return(a) cout << (a) << endl; return (a)

would do it (might be wrong) if I padronize all returns to parenthesized (or whatever this may be called). If I want to take this out, just comment out the define.

However, printing inputs seems more difficult. Is there a way I can do it, using C++ structures or with a workaroud hack?

+2  A: 

It sounds like you want to use a debugging utility to me. That will allow you to see all of the parameters that you want.

Seth M.
I don't want to see the parameters. I want to output all of them in order to do something different, like a statistical study, etc, that is not part of the utility.
Luís Guilherme
+1  A: 

If your methods are all virtual, you could use the decorator-pattern to achieve that in a very elegant way.

EDIT: From your comment above (you want the output for statistics) I conclude that you should definitely use the decorator-pattern. It is intended for this kind of stuff.

Space_C0wb0y
Subclassing would achieve the same in this very situation, wouldn't it? However that's not what I'm looking for! Both decorating and subclassing would require the same amount of code to be written than the dirty trick (putting prints everywhere). However, I would have also to change caller code.
Luís Guilherme
Well, it says in your profile that you like good design... Sadly, implementing design patterns in C++ always comes with alot of boiler-plate, but it still has the benefit of high flexibility.
Space_C0wb0y
Yes, I really like design patterns, GoF is the only book that sits at my table every time. But I think for this case is overkill. I want a temporary "turn-on"/"turn-off" ability for developers purpose.
Luís Guilherme
I apologize, I was a little edgy there. You are of course right, one has to choose the appropriate solution for each problem.
Space_C0wb0y
+4  A: 

However, printing inputs seems more difficult. Is there a way I can do it, using C++ structures or with a workaroud hack?

No.


Update: I'm going to lose some terseness in my answer by suggesting that you can probably achieve what you need by applying Design by Contract.

Daniel Daranas
Short, sweet, to the point, correct. +1.
Billy ONeal
+7  A: 

A few options come to mind:

Josh Kelley
+1 for the AOP tip! However, read the concerns I did to whoever suggest me using a debugger and to Space_C0wb0y
Luís Guilherme
Decorating or subclassing would have me to change caller code. Even being able to do it, I don't want to. It's better to make the changes in-place with defines (#ifdef STATS ... #endif) than having to put a decorating call for every object of this class created.
Luís Guilherme
+2  A: 

If you don't mind inserting some code by hand, you can create a class that:

  1. logs entry to the method in the constructor
  2. provides a method to dump arbitrary parameters
  3. provides a method to record status
  4. logs exit with recorded status in the destructor

The usage would look something like:

unsigned long long
factorial(unsigned long long n) {
    Inspector inspect("factorial", __FILE__, __LINE__);
    inspect.parameter("n", n);
    if (n < 2) {
        return inspect.result(1);
    }
    return inspect.result(n * fact(n-1));
}

Of course, you can write macros to declare the inspector and inspect the parameters. If you are working with a compiler that supports variable argument list macros, then you can get the result to look like:

unsigned long long
factorial(unsigned long long n) {
    INJECT_INSPECTOR(n);
    if (n < 2) {
        return INSPECT_RETURN(1);
    }
    return INSPECT_RETURN(n * fact(n-1));
}

I'm not sure if you can get a cleaner solution without going to something like an AOP environment or some custom code generation tool.

D.Shawley
Nice, although the varargs likely will have issues. C++ doesn't play well with varargs functions, which it will eventually need to use. They're supported, but really only for C values.
Michael E
I was thinking of variable argument list _macros_ for `INJECT_INSPECTOR` though they haven't been officially slurped into C++ yet. Varargs functions in C++ are definitely to broken to be used in any real manner. I would use a separate `parameter(name,value)` call for each parameter, make the call a template, and take advantage of iostreams for the formatting. I am using something similar in practice today ;)
D.Shawley
A: 

I would just use a logging library (or some macros) and insert manual logging calls. Unless your class has an inordinate number of methods, it's probably faster to get going with than developing and debugging more sophisticated solution.

Michael E
Logging could very well do what he is looking for, it will be slightly cleaner than printing each line, but you will have an additional library hanging around (unless he already has one).
Seth M.