| re: Question about function objects (a bit lengthy)
Victor Bazarov wrote:
[color=blue]
> "Keith P. Boruff" <kboruff@optonline.net> wrote...[color=green]
>> Currently, in my work, I'm dealing with some old and sloppy C++ code
>> (written before '93).
>>
>> I'm trying to put test harnesses around the stuff I'm working on (using
>> Boost testsuite lib FYI) to minimize breakage.
>>
>> I came across a class something like this:
>>
>> class A
>> {
>>
>> public:
>>
>> typedef void (*somefunc)(void*);
>>
>> A( somefunc aFunc) : pFunc_(aFunc) {}
>>
>> private:
>>
>> somefunc pFunc_;
>>
>> };
>>
>> For my tests, I want to get some feedback on how an object of the class
>> uses
>> the pointer to the function. For example, how many times is this function
>> called within the lifetime of a class? In theory, a functor would work
>> nicely:
>>
>> class MyFunctor
>> {
>>
>> int callCount_;
>>
>> public:
>>
>> MyFunctor() : callCount_(0): {}
>>
>> int timesCalled() const { return callCount_; }
>>
>> void operator () (void* ) { ++callCount_; }[/color]
>
> If you really want to preserve the functionality of your program, your
> functor has to "forward" all calls to the original funcion _as_if_ it
> is doing all the work. To achieve that, you need to store the actual
> function pointer there and in the operator() call the function through
> the pointer.[/color]
Actually Victor, my intention of using the functor strategy is strictly for
testing purposes. I wanted to use this as a "fake object" in my test code
not as an adapter to a real function. Sorry for the confusion.
[color=blue]
>[color=green]
>>
>> };
>>
>>
>> However, I can't do this:
>>
>> #include <iostream>
>>
>> int main()
>> {
>>
>> MyFunctor myFunc;
>> A a(&myFunc);
>>
>> // Do stuff with A
>> std::cout << "number of times function called: "
>> << myFunc.timesCalled() << std::endl;
>>
>> return 0;
>> }
>>
>> Of course, the code in main() won't work but this is something I'd like
>> to achieve.[/color]
>
> You could try achieving it through a static member function.[/color]
I think... I tried that with no results. I'll give it another shot.
[color=blue]
>[color=green]
>> Does anyone have any solutions for this that uses a functor?[/color]
>
> There can be no solution that uses a functor in this case.[/color]
Somehow, I already knew that was the answer to this question but I thought
I'd throw it out here in case someone faced something similar.
[color=blue][color=green]
>> I know I can
>> just create a *someFunc* function, pack it with some global variables and
>> read them (which is what I've done for the moment) but I was hoping a
>> solution similar to the above would be possible.[/color]
>
> You can do a bit better with a class template which would pack some
> data that you need and have the static member your 'a' object would
> call:
>
> template<..blah..> class CallCounter {
> ..blah.. // static data (instead of global objects)
> public:
> CallCounter(which_function) { /* change static data */ }
> static void* CountCalls() { call_which_function(); ++counter; }
> };
>
> ...
>
> CallCounter<whatever> cc(arguments);
> A a(cc.CountCalls);
>
> I would consider it marginally better than a proxy function with
> global variables. Just packaged a bit nicer, anyway.[/color]
Definitely! It's ugly the way I have it but the good thing is that it's just
confined to a test harness. I would never write this *proxy hack* in
production code.
Thanks for your help,
Keith |