Question about function objects (a bit lengthy)

K

Keith P. Boruff

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
 
K

Keith P. Boruff

Keith P. Boruff wrote:

public:

typedef void (*somefunc)(void*);


Depending on your newsreaders, you may not see that I put asterisks in the
right spots for this typedef.
 
V

Victor Bazarov

Keith P. Boruff said:
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_; }

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.
};


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.

You could try achieving it through a static member function.
Does anyone have any solutions for this that uses a functor?

There can be no solution that uses a functor in this case.
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.

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.

V
 
K

Keith P. Boruff

Victor said:
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.

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.
You could try achieving it through a static member function.

I think... I tried that with no results. I'll give it another shot.
There can be no solution that uses a functor in this case.

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.

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.

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top