Salutations
I'm trying to use the std::sort algorithms on specials objects.
I got a list to sort and a binary function which give me a comparison:
Interesting part of B.cpp
void B::FindClosest(vector<A*> list)
{
bool (B::*ptr)(A*,A*) = &B::Closer;
sort(list.begin(),list.end(),(this->*ptr));
// some use of this sorted list
}
bool B::Closer(A* lhs ,A* rhs)
{
if(Distance(this,lhs)<Distance(this,rhs))
{
return true;
}
else
{
return false;
}
}
And B.h :
class B : public A
public:
void FindClosest(vector<A*>);
bool Closer(A*,A*);
This seems pretty simple but i can't figure out why it's not working.
It seems to me that i'm doing something wrong on pointer to member function but cant find out what.
Here is the error msg :
agglomerate.cpp:32: error: invalid use of non-static member function
I've tried some other way to get things to work but nothing.
I'm not bound to pointer to member function, if you got a simple / different way to do this you're welcome.
Thanks a lot,
Azhrilla
You cannot use such thing, you should use std::bind or boost::bind or lambda for this case, since sort third parameter should be callable object, that receive two objects of type T.
With std::bind it will be
using namespace std::placeholders;
sort(list.begin(), list.end(), std::bind(ptr, this, _1, _2));
This line:
bool (B::*ptr)(A*,A*) = &B::Closer;
Gets a point to the member function B. To call this function you then need a class instance to call it on (the member function needs to know which conrete instance of class data it can access etc). For example
(this->*ptr)(lhs, rhs)
Calls the member function of this. If you did
B anotherB;
bool (B::*ptr)(A*,A*) = &B::Closer;
(anotherB.*ptr)(lhs, rhs)
That would call the B::Closer function but this time using anotherB and not this (assuming this was not 'anotherB')
I'm not sure what...
(this->*ptr)
...evaluates to?, but it is the problem
I think the problem is that you cannot give sort() the class instance and the member function pointer... you can only give it the member function pointer and so it has no class instance on which to call this function.
As ForEveR suggests, you could usde std::bind so that you can convert from a function withfour parameters, hls, rhs, class-instance, member-pointer. bind one to 'this' and one to the desired member function, so that the result is a function that just needs lhs and rhs.
Related
I am trying to use dlib to minimize a function where I can calculate the function and it's gradient at a given parameter value, using find_min.
As the function changes depending on input, I have defined a class with the inputs as members of the class, and two public functions which calculate the function and its gradient at the current guess of the solution:
#include <dlib/matrix.h>
typedef dlib::matrix<double,0,1> column_vector;
class Link
{
public:
// Initialisation
Link(const column_vector& predictors, const column_vector& responses)
: _predictors(predictors), _responses(responses)
{
}
// Likelihood and first derivative
double likelihood(const column_vector& b) const;
column_vector gradient(const column_vector& b) const;
protected:
column_vector _predictors;
column_vector _responses;
};
(omitting the code to calculate these functions for simplicity).
I then run through a loop of predictors and responses, minimising each case:
column_vector starting_point(2);
Link linear(x, y);
dlib::find_min(dlib::bfgs_search_strategy(),
dlib::objective_delta_stop_strategy(1e-7),
linear.likelihood,
linear.gradient,
starting_point);
However, I get a compiler error from trying to provide the non-static member functions linear.likelihood and linear.gradient from Link: 'reference to non-static member function must be called'.
I'd previously gotten this to work by overloading operator() when using only the likelihood, but can't do this with two functions (likelihood and gradient). Turning these into function pointers gives the same error.
Searching other answers I've found similar problems with trying to pass non-static member functions as arguments, but couldn't get them to work here. Is there a standard solution using template arguments I should be using to fix this?
Or am I going about this problem the wrong way entirely, and I shouldn't be using a class like this?
The arguments to dlib::find_min() have to be objects that can be called with the function-call operator(). linear.likelihood() calls the likelihood function and returns a result, but linear.likelihood by itself is not well-formed C++.
An easy solution is to use lambda expressions and to capture the object linear by reference. The lambda expression is a temporary object that is callable.
dlib::find_min(dlib::bfgs_search_strategy(),
dlib::objective_delta_stop_strategy(1e-7),
[&linear](const column_vector& a) {
return linear.likelihood(a);
},
[&linear](const column_vector& b) {
return linear.gradient(b);
},
starting_point);
So I got myself onto shaky ground by insisting on making a C++ class immitate a regular function. The class overloads the function operator, making it a functor, of course. This all works fine, until you want to pass the function pointer of this functor.
Naturally, I want to let the compiler know that we know what we're doing (lol), by doing a reinterpret_cast of this pointer. However, how do I get the address of this particular member function, since it is an overloaded operator. How does one get the address of that?
UPDATE: You asked for an example. Here is a minimal one.
So I have an interface, which I cannot change. It looks like this;
typedef void (*some_callback_t)(SomeType);'
void someFunc(some_callback_t);
Now, this is quite straight-forward; the API is setting some callback function pointer. So, the idea was to implement the callback as a functor class, by overloading the operator(), like so, as usual.
class Bah {
void operator()(SomeType);
};
Here comes the question; seeing as I cannot change the API used (the function that expects a function pointer of a certain signature), how can I then get the address of the member function and pass that?
I suspect it goes something like;
someFunc(reinterpet_cast<some_callback_t>( ? ? ? )); to make sure that the compiler won't barf at me.
Supposing that you have to use a function pointer, and that your functor has no state, you can use a lambda as glue:
void takesFunctionPointer(void (*)());
struct MyFunctor {
void operator()();
};
// ...
takesFunctionPointer([] { return MyFunctor{}(); });
How does one get the address of that?
In the same way as any other member function. The name of the function is class_name::operator(). An example:
struct class_name {
void operator()(){}
};
void (class_name::*member_function_pointer)() = &class_name::operator();
class_name instance;
(instance.*member_function_pointer)(); // in a block scope
Naturally, I want to let the compiler know that we know what we're doing (lol), by doing a reinterpret_cast of this pointer.
That's usually not what one would want to do.
I've been racking my brain over getting the syntax right on declaring, defining and finally calling a member function pointer inside my program.
I'm writing a window manager with Xlib, and am trying to enable the user to define all key bindings in a vector of Keybinds. The Keybind struct contains more member variables, which I have left out here for the sake of brevity.
Here's what I've got so far.
Keybind, a struct containing a member variable, func, that points to a MyClass member function.
struct MyBind {
MyBind(void (MyClass::*_func)(const XKeyEvent&))
: func(_func) {}
void (MyClass::*func)(const XKeyEvent&);
}
Declaration and populating of a vector that holds user-defined Keybinds.
// in my_class.hh
std::vector<MyBind*> my_binds_;
// in my_class.cc, constructor
my_binds_.push_back(new MyBind( &MyClass::do_this ));
my_binds_.push_back(new MyBind( &MyClass::do_that ));
At this point, everything compiles and runs.
Now, when I try to delegate work by iterating over the my_binds_ vector, things go wrong. It is worth noting that I've left out error handling and other member variable accesses for clarity.
void
MyClass::handle_input(const XKeyEvent& e)
{
for (const MyBind* my_bind: my_binds_) {
(my_bind->*func)(e); // erroneous line
}
}
This should be the correct syntax, but it fails to compile, stating error: ‘func’ was not declared in this scope (g++, similar error from clang++).
This is weird to me, as replacing the erroneous line of code with auto test = keybind->func; does compile.
What am I doing wrong? Is there a better way to handle user key bind definitions? Thanks!
It would be best to use std::function and forget about raw member-function pointers altogether. They will only bring you pain :)
The problem with you code is that you only have a pointer to a method but no object. Your bind struct should also store an object pointer to call the method on:
struct MyBind {
MyBind(MyClass *obj, void (MyClass::*_func)(const XKeyEvent&))
: obj(obj), func(_func) {}
MyClass *obj;
void (MyClass::*func)(const XKeyEvent&);
void operator()(const XKeyEvent& event) const
{
(obj->*func)(event);
}
}
And then use it like this:
void
MyClass::handle_input(const XKeyEvent& e)
{
for (const MyBind* my_bind: my_binds_) {
(*my_bind)();
}
}
I've added a call operator to the bind struct for convenience. Note that the ->* operator is applied to the object the method belongs to.
This is not an answer, rather a pointer to your answer or my so-question :)
You had to use
(this->*(my_bind->func))(e);
instead of:
(my_bind->*func)(e);
I have re-created your error msg and asked a question after many different attempts.
See this( pointer to your answer ;) ): How to call pointer to member function, which has been saved in a vector of custom struct?
MyBind holds the pointer to member function of some instance of MyClass. Therefore in order to call these function pointers, you need to explicitly tell using this keyword, for which instance of MyClass you want the func to be called.
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.
i have made a sample example, in this i'm trying to pass a function as argument i am getting error, could you please help me
typedef void (*callbackptr)(int,int);
class Myfirst
{
public:
Myfirst();
~Myfirst();
void add(int i,callbackptr ptr)
{
ptr(i,3);
}
};
class Mysec
{
public:
Myfirst first_ptr;
Mysec();
~Mysec();
void TestCallback()
{
callbackptr pass_ptr = NULL;
pass_ptr = &Mysec::Testing;
first_ptr.add(2,&Mysec::Testing);
}
void Testing(int a,int b)
{
int c = a+b;
}
};
The type of the callback function you're passing as parameter is not defined as part of a class. You probably should define Testing as static.
You are geting an error because you are pointing to a member function. Pointers to member functions are different. See here:
http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.1
A member function needs to know what instance it is working with (the this pointer) so it can't be called like any other function. If you moved the callback function out of the class (or made it static, which is similar to moving it out of the class) you could call it like any other function.
A more modern way of doing this is to use functors, e.g. boost::function and something like boost::bind :
C++ Functors - and their uses
how boost::function and boost::bind work
Those can hide the difference between member and global functions.
You are trying to access a member function pointer here, using a simple function pointer typedef, which will not work. Let me explain.
When you write a normal, non-member function (similar to C), the function's code actually exists in a location indicated by the name of the function - which you would pass to a function pointer parameter.
However, in the case of a member function, all you have is the class definition; you don't have the actual instance of the class allocated in memory yet. In such a function, since the this pointer is not yet defined, any reference to member variables wouldn't make sense, since the compiler doesn't have enough information to resolve their memory locations. In fact, member function pointers are not exact addresses; they encode more information than that (which may not be visible to you). For more, read Pointers to Member Functions.