How to pass a function from another class as parameter? - c++

I want to pass a function from another class as parameter in my current class. I'm trying to do something like this (I siplified the code, so you still can get the idea):
B class:
bool B::myCmpFunc(int a, int b) {
return a > b;
}
vector<int> B::sort(bool (*cmp)(int a, int b)) {
vector<int> elems = getElems();
for (int i = 0; i < elems.size() - 1; i++) {
for (int j = i + 1; j < elems.size(); j++) {
if ((*cmp)(elems[i], elems[j])) {
int aux = elems[i];
elems[i] = elems[j];
elems[j] = aux;
}
}
}
return elems;
}
And I try to call this sort function from A class:
B b;
auto sortedElems = b.sort(&b.myCmpFunc);
The problem is I get this error when I try to pass &b.myCmpFunc as parameter in A class:
Error C2276 '&': illegal operation on bound member function
expression
I also tried another things, like passing the function as b.myCmpFunct, B::myCmpFunc, &B::myCmpFunc, but I still got errors.

When you have a class function (non static function inside a class), you need to pass this/the instance of the class around, so the compiler can pass this/the instance of the object to the function, when it invokes it.
You can:
Make your function static. static functions inside a class don't use this / the object instance, so their pointers are normal.
static bool B::myCmpFunc(int a, int b) {}
b.sort(&b.myCmpFunc);
// or
b.sort(&B::myCmpFunc);
You can refactor your function to use std::function and bind this with object pointer using std::bind.
vector<int> B::sort(std::function<bool(int a, int b)> cmp) {
... no changes ...
}
b.sort(std::bind(&B::myCmpFunc, &b, std::placeholders::_1, std::placeholders::_2));
Refactor your function to take only B class functions.
vector<int> B::sort(bool (B::*cmp)(int a, int b)) {
...
(this->*cmp)(...);
...
}
b.sort(&B::myCmpFunc);
Use a lambda.
b.sort([](int a, int b) -> bool { return a < b; });
// really or
b.sort([&b](int a, int b) -> bool { return b.myCmpFunc(a, b); });
and many more (ex. template).
As the member function B::myCmpFunc doesn't seem to use this pointer nor object members, I would go with declaring it static.

You mix up pointers to ordinary functions and pointer to member functions. Those are different concepts, that are worth understanding at some point. What you can do is to make the comparison function a static and then pass a pointer to it like this:
auto sortedElems = b.sort(&B::myCmpFunc);
Otherwise, you can implement myCmpFunc as a free function, i.e., not bound to a class. Then pass it as
auto sortedElems = b.sort(&myFreeCmpFunc);
In any case, it doesn't make much sense to have a member function myCmpFunc that has no dependency on the state of its object. Making it a free function increases encapsulation and makes the comparison function reusable (apart from the fact that you could also use a std::greater<>{} function object instead.

Related

How do I Pass a Member Function to a Function as a Function Pointer?

Source of Problem https://github.com/claydonkey/PointerToMember/tree/master
Although touched on in How Can I Pass a Member Function to a Function Pointer?, I feel somewhat dissatisfied with the solutions provided, as I don't want to introduce a dependency on the Boost library.
Comparing std::function for member functions is a post that gets close to a solution but ultimately is less optimistic about the use of std::function in .
(it seems that member functions cannot be passed as function pointers)
The Problem:
A function simpleFunction which cannot be altered takes a callback pfunc:
typedef int (*FuncPtr_t)(void*, std::pair<int,int>&);
static int simpleFunction(FuncPtr_t pfunc, void *context, std::pair<int,int>& nos)
{
pfunc(context, nos);
}
This function is intended to callback the method memberFunction in class SimpleClass:
NB removed void from original post as it better represents a real world usage.* was int memberFunction(void*, std::pair<int,int>& nos)
class SimpleClass {
public:
int memberFunction(std::pair<int,int>& nos) { return nos.first + nos.second; }
};
I expected the following to work:
MemFuncPtr_t MemFunction = &SimpleClass::memberFunction;
simpleFunction(obj.*MemFunction, nos);
but obj.*MemFunction has a type: int (SimpleClass::)(std::pair<int,int>&)
and it needs to be: int (*)(std::pair<int,int>&)
(wheras (obj.*MemFunction) (nos); returns as expected)
I can create and pass a trampoline:
int functionToMemberFunction(void* context, std::pair<int,int> & nos) {
return static_cast<SimpleClass*>(context)->memberFunction(nos);
}
and pass it
simpleFunction(&functionToMemberFunction, &obj, nos);
but it compiles to around 40 instructions.
I can pass a lambda:
simpleFunction((FuncPtr_t)[](void* , std::pair<int,int> & nos) {
return nos.first + nos.second;
}, &obj, nos);
That's surprisingly well optimised but a bit ugly and syntactically cumbersome.
(NB Both and lambdas require C++11)
I can add a static member to SimpleClass:
class SimpleClass {
public:
int memberFunction(void*, std::pair<int,int>& nos) { return nos.first + nos.second; }
static int staticFunction(void*, std::pair<int,int> & nos) { return nos.first + nos.second; }
};
FuncPtr_t StaticMemFunction = &SimpleClass::staticFunction;
and pass it
simpleFunction(StaticMemFunction, nullptr, nos);
and that's just, well ... a static function inside a class.
I can use the <functional> header:
using namespace std::placeholders;
std::function<int(std::pair<int,int>&) > f_simpleFunc =
std::bind(&SimpleClass::memberFunction, obj, _1);
auto ptr_fun = f_simpleFunc.target<int (std::pair<int,int> & ) >();
and try and pass it...
simpleFunction(*ptr_fun, nos);
but ptr_fun reports null.
Looking at the x86 assembly - I am at a loss at how memory is addressed, calling a member function (there are an extra 5 instructions [3 mov, 1 lea and 1 add] over the StaticMemFunction call). I can only imagine that this is down to locating the class instance in memory and then the function within it.
All the suggestions have been useful and I think if I collate them all and return to the original problem, I may have a solution that works for me.
So I thought a solution would be derived from:
simpleFunction(([](void* context,std::pair<int, int> & nos) {
return nos.first + nos.second;
}), &obj, nos);
to become:
simpleFunction(([&](void* context,std::pair<int, int> & nos) {
obj.memberFunction(nos);
}), &obj, nos);
right?
error: cannot convert main()::<lambda(std::pair<int, int>&, void*)> to int (*)(std::pair<int, int>&, void*)
Lambdas that accept closures cannot be cast to a function pointer
The closure type for a lambda-expression with no lambda-capture has a
public non-virtual non-explicit const conversion function to pointer
to function having the same parameter and return types as the closure
type’s function call operator. The value returned by this conversion
function shall be the address of a function that, when invoked, has
the same effect as invoking the closure type’s function call operator.
This makes sense as function pointers carry no state and this is why simpleFunction was gifted with a context pointer void* context (like most callbacks!), which is in turn handled by pFunc- the function pointer. (The context being the SimpleObject instance obj whose member function we wish to delegate to.)
Ergo a good solution seems to be:
solution 1
simpleFunction(([](void* context, std::pair<int,int>& n) {
return static_cast<SimpleClass*>(context)->memberFunction(n);
}), &obj, nos);
NB If obj is moved from local -> global scope the lambda would not require the object to be passed in at all. but that changes the original problem.
Incredibly, if the member-function has no calls to the class within which it resides, it behaves as a static function, the lambda obviating the need for the class instance
solution 2
simpleFunction(([](void* context, std::pair<int,int>& n) {
return static_cast<SimpleClass*>(context)->memberFunction(n);
}), nullptr /* << HERE */, nos); //WILL WORK even though the context is null!
This works perfectly as a solution to the original question: the member function indeed does not rely on anything outside the function scope (is this expected C++ behaviour or a happy hack?).
In conclusion, in trying to compose a simple analogy to a real world problem I have been naive in my the original question and I really want all the functionality of a member-function so solution 1 seems more realistic.
I am little more savvy in distinguishing between member functions and c functions - I spose the clue was in the name member (of a class)
This was all part of a learning experience and the source code including move-semantics solutions is in the link in the original post.
Implement a simple trampoline with a lambda:
#include <iostream>
typedef int (*FuncPtr_t)(void*, int);
static int simpleFunction(FuncPtr_t pfunc, void *context, int nos)
{
return pfunc(context, nos);
}
struct A {
int i;
int pf(int nos) { std::cout << i << " nos = " << nos << "\n"; return i; }
};
int main() {
A a { 1234 };
// could combine the next two lines into one, I didn't.
auto trampoline = [](void *inst, int nos) { return ((A*)inst)->pf(nos); };
simpleFunction(trampoline, &a, 42);
}
http://ideone.com/74Xhes
I've modified it to consider the assembly:
typedef int (*FuncPtr_t)(void*, int);
static int simpleFunction(FuncPtr_t pfunc, void *context, int nos)
{
return pfunc(context, nos);
}
struct A {
int i;
int pf(int nos) { return nos + i; }
};
int f(A& a) {
auto trampoline = [](void *inst, int nos) { return ((A*)inst)->pf(nos); };
return simpleFunction(trampoline, &a, 42);
}
Compiled with -O3 we get:
f(A&):
movl (%rdi), %eax
addl $42, %eax
ret
https://godbolt.org/g/amDKu6
I.e. the compiler is able to eliminate the trampoline entirely.
std::function<> plus lambdas are a nice way to go. Just capture the this in the lambda, an do what you need. You don't event need to write a separate callback if what is being executed is small. Plus std::function is required to not need a heap allocation for lambda that only captures a single pointer.
class A {
std::function <void()> notify;
void someProcessingFunction () {
// do some work
if (notify != nullptr)
notify ();
}
};
class B {
void processNotification () {
// do something in response to notification
}
};
int main ()
{
A a;
B b;
a.notify = [&b] () { b.processNotification (); };
a.someProcessingFunction ();
}
The usual approach is to pass the object as your callback data, as you do in the first example. Any overhead is likely a consequence of the calling convention on your target (or perhaps too low a setting on your compiler's optimiser).
In these circumstances I use a fusion of your first two methods. That is, I create a trampoline, but make it a static function inside the class, to avoid clutter. It does not do what the member function does (as in your second example): it just calls the member function.
Don't worry about a handful of instructions in the calling process. If you ever do need to worry that much about clock cycles, use assembler.

Cannot carry object to function properly C++

cliques is my class object. All my class commands work when I use them in my main but for some reason I cannot make changes to my heaps or stacks through my functions. I tried using reference markers on my function parameters but still I'm having ussues. Maybe I've done the reference incorrectly. Does anyone have any ideas what I might be doing wrong?
This is one of my functions:
void UpdateTopK(cliques C, vector<cliques> minheap) {
if (C.getclique_size() < CliqueSize) {
return;
}
else if (minheap.size() < Solutions) {
minheap.push_back(C);
push_heap(minheap.begin(), minheap.end(), min_iterator());
}
else if (minheap.size() == Solutions and C.getMaxclique_prob() > minheap.front().getMaxclique_prob()) {
pop_heap(minheap.begin(), minheap.end(), min_iterator());
minheap.pop_back();
minheap.push_back(C);
push_heap(minheap.begin(), minheap.end(), min_iterator());
}
This is part of my main:
stack <cliques> cstack;
vector<cliques> max_heap;
make_heap(max_heap.begin(), max_heap.end(), max_iterator());
vector<cliques> min_heap;
make_heap(min_heap.begin(), min_heap.end(), min_iterator());
for (int i = 0; i < 5; i++) {
cliques temp(i);
cstack.push(temp);
}
while (!cstack.empty()) {
cliques temp = cstack.top();
cstack.pop();
bool pruned = GenerateChildren(temp, min_heap, max_heap, cstack, graph);
if (!pruned) {
UpdateTopK(temp, min_heap);
}
}
You are passing arguments by value, this implies that parameters are copied before being passed to the function.
So every modification inside a method refers to the local copy only. Try passing values by references, eg:
void UpdateTopK(cliques& C, vector<cliques>& minheap)
^ ^
Mind that an object that needs to be passed to a function without copy and without being edited should be passed by const T& to specify this.

How to call stl::nth_element with a member function inside this class?

I want to use the function nth_element with my own sorting function (which should have access to the data of the object) within a class. Currently, I am doing the following:
class Foo
{
public:
glm::vec3 *points;
int nmbPoints;
bool idxPointCompareX(int a, int b);
void bar();
}
bool Foo::idxPointCompareX(int a, int b)
{return points[a].x < points[b].x;)
void Foo::bar()
{
stl::vector<int> idxPointList;
for(int i = 0; i < nmbPoints; i++) idxPointList.push_back(i);
stl::nth_element(idxPointList.first(),idxPointList.first()+nmbPoints/2,idxPointList.end(), idxPointCompareX);
}
Of course, this did not work and I got the error: "reference to non-static member function must be called". After that, I had a look at Reference to non-static member function must be called, How to initialize std::function with a member-function? and some other questions on here. I understand why this did not work, but I'm unsure how to solve this.
Can someone help me and tell me how to solve this problem?
To take the address of a member function you need to use the correct syntax, i.e. &Foo::idxPointCompareX not just idxPointCompareX
But you also need a Foo object to call the function on, so you would need to bind one to it. Presumably you mean to call it on this so you could use std::bind:
using namespace std::placeholders;
stl::nth_element(begin, begin+n, end,
std::bind(&Foo::idxPointCompareX, this, _1, _2));
Or simpler, use a lambda function:
stl::nth_element(begin, begin+n, end,
[this](int a, int b) { return idxPointCompareX(a, b);}
);
This creates a lambda function that captures this and passes its arguments on to the idxPointCompareX function on the captured this pointer.
idxPointCompareX is a member function, i.e. it cannot be called without some reference to a Foo object. Looking at its definition though, it seems that it doesn't need to be a member since it's purely defined in terms of its arguments.
You could make it a static function (i.e. a "class function") or a free function and then pass that to std::nth_element.
You can't call an object method before it is created, so you have some options here:
Make the method static
Leave the constructor empty and move all into an init method where you call the compare part
Use a lambda
Examples:
Static method:
static bool idxPointCompareX(glm::vec3 a, glm::vec3 b)
{return a.x < b.x;)
Init method:
Foo::bar()
{
stl::vector<int> idxPointList;
for (int i = 0; i < nmbPoints; i++)
idxPointList.push_back(i);
}
Foo::init()
{
stl::nth_element(idxPointList.first(),
idxPointList.first()+nmbPoints/2,idxPointList.end(),
idxPointCompareX);
}
Lambda:
Foo::bar()
{
stl::vector<int> idxPointList;
for (int i = 0; i < nmbPoints; i++)
idxPointList.push_back(i);
stl::nth_element(idxPointList.first(),
idxPointList.first()+nmbPoints/2,idxPointList.end(),
[](int a, int b){return points[a].x < points[b].x;));
}
I would go for the lambda version myself.

C++ vector remove_if pairs

Im trying to remove pairs from vector with remove_if, but im getting errors
bool MyClass::isSingleTag(const pair<int,string> & val) {
string tag = val.second;
int posImg, posBr;
posImg = tag.find("<img");
posBr = tag.find("<br");
if (posImg == -1 && posBr == -1) {
return false;
} else {
return true;
}
}
void MyClass::deleteSingleTags() {
vector<pair<int,string>>::iterator last_iter;
last_iter = remove_if(allTags.begin(), allTags.end(), &MyClass::isSingleTag);
allTags.erase(last_iter, allTags.end());
}
Errors: http://pastebin.com/1FCWRVDG
A pointer to a member function isn't callable without an object of the class the function is member of.
Make isSingleTag static - taking its address results in a plain function pointer. Alternatively, make it a free function, since it looks like it's got no bussiness being a member function in the first place (it doesn't access any other members, does it?).
The other option (for when you legitimately need to be a member function) is to bind it to a class object, using std::bind:
MyClass obj;
auto func = std::bind(&MyClass::isSingleTag, obj);
Now func is a callable that you can pass to the algorithm.

C++ static object Class function

Some code:
Please see the class myClass below . it has a constructor and a public recursive function find. Please see code:
#include <iostream>
using namespace std;
class myClass{
public:
myClass() {
//do stuff
}
int find(int i) {
static int j = 10;
if (i > 15)
return i;
j = j + 1;
return i * find(j + 1);
}
};
int main()
{
myClass mC1 ,mC2;
cout<< " 1.... return value = "<< mC1.find(10);
cout<< " \n 2... return value = "<< mC2.find(10);
return 1;
}
output:
1.... return value = 5241600
2.... return value = 170
The above progemn has a class myclass having a function find .. "find" function has a variabe . This is static which is required as i wanted a recursive function . Problem is static varible has life of a program & binded to class .
However I want the static to be object specfic and not class scope . I wanted both the function calls to return me same value .
Simply put , how to make a static varable in a class function , to be per object and not for whole class...
Do you need a member variable?
Hope the following code helps.
Best regards
Sam
class myClass{
public
myClass() {
m_j = 10;
}
private:
int m_j; // private member variable for find algorithm;
int find(int i) {
if(i>15)
return i;
m_j= m_j+1;
return i * find(m_j+1);
}
};
If you want a per object variable you need to make it a member of the respective object. There is no way to declare a variable inside a function to be specific to objects. The way you use use static member could be changed to be non-static anyway, i.e., you would get the necessary context: Make the function non-static and store the data in the object as needed.
That said, just because a function is recursive doesn't mean that it needs any sort of static context. Normally, all the necessary context is passed to the recursive function as parameters in which case the system keeps the necessary state on the stack. Since the stack is relatively limited in size you want to make sure that you don't need too much context in recursive functions with deep call stack.
Since you probably don't want to require the user to pass in some internal context, the find() function in the the interface would probably just delegate to the recursive function providing the necessary context. For example:
int find(int j, int i) {
if (15 < i) {
return i;
}
++j;
return i * find(j, j + 1);
}
int find(int value) {
return find(10, value);
}
(I'm not sure if I got the desired logic right because I didn't quite get what the function is meant to do...).