How to create a function pointer from a function with certain parameters fixed in C++
Suppose I want to call a function f that asks for a function pointer of type
int (*foo)(int)
The function is something like
double f( int (*foo)(int))
I have a function that does this, but it takes another object.
int bar(int, MyClass*)
This object is created at runtime, say
int main()
// ... read some file / input
MyClass myclass = MyClass(input);
// Now pass the function pointer
double retval = f( bar( int, &myclass))
Is there any way to implem开发者_JAVA技巧ent the last line? I am looking for an answer without global objects.
No.
Do you have any influence over the function f
? In C++, this would
normally be either a template which would accept any callable object, or
it would use a simple interface from which you could derive. In either
case, you would define a class which could contain the additional data.
Taking a pointer to a function, as such, is very poor design.
Edit to account for the fact that f
cannot be modified:
Since you can't modify f
, the only solution I can think of is using some sort of global variable together with a forwarding function:
int bar(int i, MyClass * mc);
namespace bar_parameters
{
MyClass * mc = 0;
}
int binded_bar(int i)
{
return bar(i, bar_parameters::mc);
}
int main()
{
MyClass myclass(input);
bar_parameters::mc = &myclass;
double retval = f(binded_bar);
}
This is quite ugly, however...
It is not possible to bind parameters of a function. However, it is possible with functor (function object).
The first thing you need to do is to modify f
's parameter to make it a function object such as std::function
or boost::function
, instead of a function pointer:
double f(std::function<int (int)> foo);
You can use this function either with function pointers or functors with the correct signature.
After that, you can use binding methods such as std/boost::bind
(or bind1st
/bind2nd
in C++03):
double retval = f(std::bind(bar, _1, &myclass));
If you don't have access to Boost or C++0x, you can use the usual technique which consists in making the parameter template in order to accept any callable entities (function pointers and functors):
template <typename Func>
double f(Func foo);
The drawback of this approach is that the signature of the function is only enforced by the way you use it in f
.
To bind the second parameter, you can then use ptr_fun
to convert a function pointer to a function object, and bind2nd
to actually bind the parameter:
double retval = f(std::bind2nd(std::ptr_fun(bar), &myclass));
You can achieve something similar by using Boost.Bind. This is now part of the C++ standard and may even be already available with your compiler. Note that Boost.Bind would still require that you modify f
's signature. If that is not possible you could do something like
MyClass* _only_to_be_used_by_ugly;
int ugly(int i) {
return bar(i, _only_to_be_used_by_ugly)
}
int main() {
_only_to_be_used_by_ugly = MyClass(input);
double retval = f(ugly);
}
But I'd be the first to advise against a similar approach.
In your case you will have to do something evil, like:
MyClass* g_myclass = 0;
int my_f(int i) {
return bar(i, g_myclass);
}
int main()
// ... read some file / input
MyClass myclass = MyClass(input);
// Now pass the function pointer
g_myclass = &myclass;
double retval = f(&my_f);
g_myclass = 0; // no longer needed (you hope).
...
}
YMMV. If the function pointer you pass is retained somewhere and used again later then you will be in for trouble.. In which case you would need to have a list of static functions and a global array of pointers to MyClass and allocate/free from this list as neccessary. You can generate the functions using a recursive template metaprogram. Not nice but possible.
OR, figure out how to generate the required assembler to do the binding and encode the MyClass pointer in the assembly instructions. The function is then allocated on the heap. Not very portable but should also be do-able. I've never tried this though so cannot guarantee it would work or be easy to do. The code would also look hideous.
精彩评论