Question about function objects (a bit lengthy) 
July 23rd, 2005, 01:49 AM
| | | |
Hello all,
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_; }
};
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.
Does anyone have any solutions for this that uses a functor? 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.
Please don't say "change the interface of the tested class". At this time,
that's not possible (though I'd like to).
If I haven't been clear on anything here, just ask.
Thanks,
Keith | 
July 23rd, 2005, 01:49 AM
| | | | re: Question about function objects (a bit lengthy)
Keith P. Boruff wrote:
[color=blue]
> public:
>
> typedef void (*somefunc)(void*);[/color]
Depending on your newsreaders, you may not see that I put asterisks in the
right spots for this typedef. | 
July 23rd, 2005, 01:49 AM
| | | | re: Question about function objects (a bit lengthy)
"Keith P. Boruff" <kboruff@optonline.net> wrote...[color=blue]
> 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=blue]
>
> };
>
>
> 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=blue]
> 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=blue]
> 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=blue]
> [..][/color]
V | 
July 23rd, 2005, 01:50 AM
| | | | 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 |  | | | | /bytes/about
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over 225,714 network members.
|