I don't understand why the following code compile and works:
template<typename Predicate>
void foo(Predicate p) {
}
bool g(int n) {
}
void user(int n) {
foo(g);
}
foo is supposed to get a function object that will run on a data structure but I made the method simpler, because what I don't understand is how can this works? A method isn't an object. The normal way to do it is to create a new class, override operator() and then send an instance of that class.
Well, in this case the Predicate parameter is substituted by a function pointer of type bool (*func) (int). Nothing wrong with that...
The Predicate template argument can be almost any type. So you can use it for function pointers and classes as well as the basic types.
If you use the function argument p as a function, then it can be anything that is callable, like a function pointer, an object whose class have an operator() member function, a pointer to a static member function, a std::bind object, a std::function object or a lambda expression.
It can't be a pointer to a member function though, because to call a pointer to a member function you need an instance to call it on. For this use std::bind.
Related
This question already has answers here:
C++ function pointer and member function pointer
(3 answers)
Closed 2 years ago.
typedef void (*funcPtrType)(); // function pointer type
map<char,funcPtrType>eventGroups;
void addSharedEvent(char groupIndex,void (*receiverFunc)() ){
if(groupIndex==0)
return;
eventGroups[groupIndex]=receiverFunc;
}
It works if adding inline functions but not if using non inlined class member functions like below...
void MainWin::uiValsUpdated()
{
}
void MainWin::test()
{
//invalid
wSync.addSharedEvent(4,&uiValsUpdated);
}
How to make universal pointer for accessing functions in various types of classes?
Alternatively could define class types also but still in universal manner like Qtˇs signals and slots for example.
typedef void (*funcPtrType)(); // function pointer type
Avoid obfuscating pointer types like this.
It works if adding inline functions but not if using non inlined class member
It has nothing to do inline vs non-inline, and everything to do with the fact that a function pointer cannot point to a non-static member function.
How to make universal pointer for accessing functions in various types of classes?
A function pointer can point to functions except non-static member functions as long as the prototype matches. To call such function, no class instance is required. Example:
void free_function() {}
auto fun_ptr = &free_function;
fun_ptr();
A pointer to member function can point to non-static member functions of a particular class with matching prototype. In order to call such pointed function, there must be an instance of the class. Example:
struct foo {
void member_function(){}
};
auto mem_fun_ptr = &foo::member_function;
foo f;
f.*mem_fun_ptr();
A function object can be used as a wrapper, and it can call any type of functions. If you want to call a member function, the needed instance can for example be stored as a member. A lambda is a shorthand for creating such function object. Example:
auto lambda_free = [] {
free_function();
}
auto lambda_member = [f] {
f.member_function();
}
lambda_free();
lambda_member();
Type erasure techniques can be used to hide the type of various function objects, since they can be called in the exactly same manner. Standard comes with a template for such purpose: std::function. Example:
std::function<void()> fun_wrapper;
fun_wrapper = lambda_free;
fun_wrapper = lambda_member;
fun_wrapper = fun_ptr;
//fun_wrapper = mem_fun_ptr; // nope; there is no instance of foo
Pointers to free functions are very different from those that point to member functions. Not only is the syntax different, member function pointers also need a this first argument - the instance of their class they are supposed to operate on. You cannot use the same map to store both, if you intend to deal with raw (member) function pointers.
One solution is some kind of type erasure; you can store std::function objects in your map:
map<char, std::function<void()>>eventGroups;
void addSharedEvent(char groupIndex, const std::function<void()>& callback){ ... }
You can construct the parameter by plain function pointers, and in case of member functions usage of std::bind or a lambda.
std::vector<char>function(std::string word) {
}
namespace::json getList(){
function();
}
I was just wondering if im suppose to call the function on top by including std::function(argument)
No, you don't need nor should you use the std::function class to call function. The std::function class is more like a function pointer wrapper. It lets you work with functions as data more easily.
For example, std::function<T> func represents some parameterless function that returns an object of type T.
Refer to the documentation for std::function for more information.
In my code I would like to call different functions by the same name. So I used pointers, and I did work with static functions, now I would like to do the same with non-static functions and it doesn't work at all.
class Amrorder
: {
public:
....
void (*fkt)(real&, const real);
void fktAcPulse(real &rhoRef, const real y);
void fktAcPulseSol(real &rhoRef, const real y);
...
}
void Amrorder::initData(a)
{
...
switch(method){
case 2://
Amrorder::fkt=&Amrorder::fktAcPulse;
break;
case 222://
Amrorder::fkt=&Amrorder::fktAcPulse1d;
break;
}
...
for(int i=0; i<ng; ++i){
Amrorder::fkt(rhoRef, yRef);
...
}
...
}
The code is quiet big so I hope the part above is enough to understand what I want to do.
Thanks for your time!
It doesn't work because your fkt has type:
void (*)(real&, const real);
and you're trying to assign it to, e.g., &Amrorder::fktAcPulse, which has type:
void (Amrorder::*)(real&, const real);
Notice the difference. The latter is a pointer-to-member function, not just a pointer to function. These have different semantics. A pointer to function can just be called (e.g. fkt(a, b)), but a pointer to member function needs to be called on an object (e.g. (obj.*pm)(a, b)).
For simplicity, since you probably just want "something that I can call with a real& and a const real", you may want to consider the type-erased function object: std::function:
std::function<void(real&, const real)> fkt;
This can be initialized with any callable that matches the arguments, so you can assign it to a free function:
void foo(real&, const real) { ... }
fkt = foo;
A static member function:
struct S { static void bar(real&, const real) { ... } };
fkt = &S::bar;
Or a member function, as long as its bound:
fkt = std::bind(&Amrorder::fktAcPulse, this);
fkt = [this](real& a, const real b){ return this->fktAcPulse(a, b); };
The key is that you need an instance of Amrorder to call fktAcPulse, and using std::function lets you use either std::bind or a lambda to store that instance in with the functor itself.
The type of fkt declares a function pointer to a free-standing function or a static member function. But you want to assign a non-static member function pointer to it. So fkt needs to be of the type of a non-static member function pointer of class Amrorder. That type is spelled
void (Amrorder::*fkt)(real&, const real);
// ^^^^^^^^^^
When invoking a function pointer to a non-static member function, you need to specify on which object you want the member to be called (which normally defaults to this when calling a member function directly with its name).
The syntax for this is quite strange. It requires another pair of parentheses and depends on wether you call it on a pointer or an object itself:
(object.*functionPointer)(arguments);
(pointer->*functionPointer)(arguments);
So if you just want to call the function on the this pointer, you need to write
(this->*fkt)(rhoRef, yRef);
(Note that you don't need to specify the class in your code everywhere. Amrorder:: can be removed in front of every function name inside the definition of a member function of the same class.)
When you call a non-static method of a class, the compiler needs to know which instance of the class you want to execute against. So there is a hidden parameter in the call, which is a pointer to the instance.
So you need to write something like this:
Amrorder::fkt=bind( &Amrorder::fktAcPulse, this );
So I have this function:
void EventDispatcher::Subscribe(string eventName, void (*callback)(void *))
{
....
}
I am trying to pass class member function as a callback parameter there.
typedef void (*method)(void*);
void EventTester::RunTests()
{
_dispatcher = new EventDispatcher();
Event eventOne("one");
_dispatcher->Register("one", eventOne);
method p = &onOne;
_dispatcher->Subscribe("one", p);
}
void EventTester::onOne(void *args)
{
std::cout<<"Event one\n";
}
obviously this doesn't compile because onOne is not static and a member function. Is there any way of making it work this way?
You could use boost in C++03 or std::bind and std::function in C++11:
typedef boost::function<void(void*)> func_type;
void EventDispatcher::Subscribe(const string& eventName, const func_type& func_)
{
if ( ! func_.empty() ) {
// you could call the function
func_(NULL);
}
}
//Register looks like in a member function of EventTester:
...
_dispatcher->Subscribe("one",boost::bind(&EventTester::onOne,this,_1));
...
I'm going off the assumption that you have the ability to modify the signature of Subscribe. If not, my answer may not apply.
As you already noted, your pointer-to-member (aka method) is not the same as a plain function pointer. To use a pointer-to-member, you have to supply the class instance to call the function on as part of the method execution.
You could modify Subscribe to explicitly take in a pointer-to-member, which would expect an additional argument (the class instance). You would need Subscribe to store both the function pointer, and a pointer to your object instance. This would then require that all callbacks be implemented as pointers-to-members.
The preferred way to solve this problem is to use bind (either std::bind or boost::bind).
You would need to change your Subscribe function to take in a std/boost::function object instead of an explicit function pointer. This would permit callers of the Subscribe method to pass in any callable object (See the examples in the documentation of std::function)
You can then use bind to connect your class instance to your method pointer. This will return a functor object which will do the work of holding both your pointer-to-member and a pointer to your class instance.
For an example of how to use bind, see this link
I'm having some trouble creating a static wrapper function using template parameters. I don't want to pass the function directly to the wrapper function, because it needs a specific signature int (lua_State *) so that it can be passed into the following function:
lua_pushcfunction(L, function);
(That's right, I'm going for an auto-generated lua wrapper.)
My first thought is to create a template function with a function pointer as a non-type template argument.
template <void(* f)(void)>
int luaCaller(lua_State * _luaState)
{
f();
return 0;
}
So far, this is looking pretty good. This function has the proper signature, and calls a function I pass in via template argument.
&(luaCaller<myFunc>)
My problem arises when I try to wrap this in another function. Non-type template parameters must be externally linked, and thus the following fails:
void pushFunction(lua_State * _luaState, void(* _f)(void))
{
lua_pushcfunction(_luaState, &(luaCaller<_f>));
}
Which makes sense, because the address of the function needs to be known at compile time. You can't throw in just any pointer and expect the compiler to know which classes to create. Unfortunately, if I add a function pointer that is known at compile time it still fails. The value of the function pointer is being copied into _a, and therefore _a is still technically not known at compile time. Because of this, I would expect the following to work:
void pushFunction(lua_State * _luaState, void(* const _f)(void))
{
lua_pushcfunction(_luaState, &(luaCaller<_f>));
}
or maybe
void pushFunction(lua_State * _luaState, void(* & _f)(void))
{
lua_pushcfunction(_luaState, &(luaCaller<_f>));
}
In the first case, because the value isn't allowed to change, we know that if it is externally linked, it will still technically be externally linked. In the second case it's being passed in as a reference, which would mean it should have the same linkage, no? But neither of these attempts work. Why? Is it possible to circumvent this somehow? How can I cleanly auto generate a function that calls another function?
The const qualifier means you aren't allowed to change something, not that it's a compile-time constant. The initial value of _a is determined at runtime when the function is called, and for a * const &a, the value can even change at runtime by some external means such as another thread, if the object underlying the reference is not const.
To make the fully templated wrapper work, you need to give the compiler enough information to compile a function for each possible template argument, and provide logic to switch among those functions. The template system generates and organizes related functions, but it's not a dynamic dispatcher.
If you can add the function pointer to the lua_State object and eliminate the template parameter, that would be one solution.
Your solution would work if make the function pointer a template argument to doCaller, but that would defeat its purpose.
Rather than using a non-type function-template approach in order to bind the secondary function you want to call inside the wrapper-function, you could use a struct with a static luaCaller method. That should allow you to maintain the function signature you need for passing luaCaller to lua_pushcfunction.
So for instance, you could have a struct that looks something like the following:
template<void (*f) void>
struct wrapper
{
static int luaCaller(lua_State * _luaState)
{
f();
return 0;
}
};
template<typename Functor>
void doCaller(lua_State * _luaState, Functor wrapper)
{
Functor::luaCaller(_luaState);
}
then call it like:
doCaller(&luaState, wrapper<my_func>());