Class non-static method pointer to global function - c++

I'm trying to point a class method to a global function, i've seen this
but how i can't do it without instance?.
Consider this:
class x
{
public:
int(x::*GetVal)(int);
};
int RtX(int a)
{
return a * 4;
}
// declaration
int(x::*GetVal)(int) = (int(x::*)(int))&::Rtx; // :: global? // error
int main()
{
x a;
cout << (a.*GetVal)(4) << endl;
}
This returns me the error:
[Error] invalid cast from type 'int ()(int)' to type 'int
(x::)(int)'

x::GetX is a pointer to member. These are deeply complicated beasts, and you can't get them to point to non-member functions. The following code will work:
#include <iostream>
int RtX(int a) // Global non-member function
{
return a * 4;
}
class x
{
public:
int(x::*GetVal)(int);
// This is an instance member function which acts as a proxy and calls the
// the global function
int RtX(int a) { return ::RtX(a); }
};
int main()
{
x a;
a.GetVal =&x.RtX; // Assign the member variable. Could do this in the
// constructor. **NOTE** No casts!
std::cout << (a.*GetVal)(4) << std::endl;
}
If you find yourself reaching for a cast when dealing with function pointers and pointers-to-member-functions, stop - you are almost certainly doing it wrong, and while it will compile, it is very likely not to run properly.
Alternatively, as noted in the comments, use std::function.
#include <iostream>
#include <functional>
int RtX(int a)
{
return a * 4;
}
class x
{
public:
std::function<int(int)> GetVal;
// Initialize GetVal in the constructor.
x() : GetVal(RtX)
{}
// Alternatively, you can initialize the variable in with a default
// initialization. You can also declare the member const if you don't want to
// change it later.
const std::function<int(int)> gv = RtX;
/*
};
int main()
{
x a;
std::cout << a.GetVal(4) << std::endl;
}

Non static member functions need an instance in order to be called. You might consider using a static function member instead and if you also use std::function, you might get a simple code to assign your member function without instance:
#include <iostream>
#include <functional>
int RtX(int a)
{
return a * 4;
}
class x
{
public:
static std::function<int(int)> GetVal;
};
std::function<int(int)> x::GetVal = RtX;
int main()
{
x a;
std::cout << (a.GetVal)(4) << std::endl;
}

Related

C++ - calling a member function of another class using a pointer

I'm testing, trying to call a member function being passed as a parameter,
the member function has to be one of another class.
this is an example, which gives an error:
"pointer-to-member selection class types are incompatible ("B" and
"A")"
This is the code, what am I doing wrong?
#include <iostream>
using namespace std;
class A {
private:
public:
void fA(int x) {
cout << "hello" << endl;
}
void fB(int x) {
cout << "good bye" << endl;
}
A() {
}
};
class B {
private:
void (A:: * f)(int) = NULL;
public:
B(void (A:: * f)(int)) {
this->f = f;
}
void call() {
(this->*f)(10); //What's wrong here?
}
};
A a = A();
B b = B(&(a.fA));
B b2 = B(&(a.fB));
int main(void) {
b.call();
b2.call();
}
&(a.fA) is not legal C++ syntax. &A::fA is. As you can see, there is no object of type A anywhere of this syntax. &A::fA is just a pointer to a member function, not a pointer-to-member-together-with-an-object combo.
Now in order to call that pointer-to-member, you need an object of class A. In class B, you don't have any. You need to get one in there somehow, and call the function this way:
(a->*f)(10);
where a is a pointer to that object of class A.

Call a C-style function address with std::bind and std::function.target using a method from object

I have a C-style function, which stores another function as an argument. I also have an object, which stores a method that must be passed to the aforementioned function. I built an example, to simulate the desired situation:
#include <functional>
#include <iostream>
void foo(void(*f)(int)) {
f(2);
}
class TestClass {
public:
std::function<void(int)> f;
void foo(int i) {
std::cout << i << "\n";
}
};
int main() {
TestClass t;
t.f = std::bind(&TestClass::foo, &t, std::placeholders::_1);
foo( t.f.target<void(int)>() );
return 0;
}
What is expected is that it will be shown on screen "2". But I'm having trouble compiling the code, getting the following message on the compiler:
error: const_cast to 'void *(*)(int)', which is not a reference, pointer-to-object, or pointer-to-data-member
return const_cast<_Functor*>(__func);
As I understand the use of "target", it should return a pointer in the format void () (int), related to the desired function through std :: bind. Why didn't the compiler understand it that way, and if it is not possible to use "target" to apply what I want, what would be the alternatives? I don't necessarily need to use std :: function, but I do need the method to be non-static.
This is a dirty little hack but should work
void foo(void(*f)(int)) {
f(2);
}
class TestClass {
public:
void foo(int i) {
std::cout << i << "\n";
}
};
static TestClass* global_variable_hack = nullptr;
void hacky_function(int x) {
global_variable_hack->foo(x);
}
int main() {
TestClass t;
global_variable_hack = &t;
foo(hacky_function);
return 0;
}
//can also be done with a lambda without the global stuff
int main() {
static TestClass t;
auto func = [](int x) {
t->foo(x); //does not need to be captured as it is static
};
foo(func); //non-capturing lambas are implicitly convertible to free functions
}

Can a default lambda parameter have access privilege like the class itself? [duplicate]

Let's say, I have a class:
class A {
int a;
};
And I have a lambda:
auto function = [](A* a) {
a->a; // <== gives an error in this line.
};
function(new A);
Is there any way to use a private member/method inside a lambda? - It's not necessary to pass the pointer to the lambda - it may be a capture-by or something else.
All reasonable schemes are welcome.
You can do it by creating a friend function that returns the lambda function. It inherits the friend access:
struct A {
friend std::function<void(A&, int)> f();
private:
int i;
void test() {std::cout << "test: " << i << "\n";}
};
std::function<void(A&, int)> f() {
return [] (A &a, int i) {a.i = i; a.test(); };
}
int main() {
A a;
f()(a, 13);
return 0;
}
In order to make a lambda a friend, you need to befriend a class or a function where the lambda is defined. Here is a complete example:
#include <iostream>
using namespace std;
class A {
int a;
public:
A(int _a) : a(_a) {}
friend int foo(A*); // Declare foo(A*) a friend of A
};
int foo(A* aa) {
auto function = [](A* a) {
return a->a; // Now foo(A*) can access A::a, which is private
};
return function(aa);
}
int main() {
A a(123);
cout << foo(&a) << endl;
return 0;
}
Here is a running demo on ideone.
using std::function takes extra resource, so I recomendet using friend/or method function to access private member (friend function implicit inlined):
class A{
int a;
friend int access_member(A*a){ return a->a;}
};
-----------------------------------------
auto function = [](A*a){ return access_member(a); }
Live example
EDIT: I personally like std::function, but don't forgot, std::function always takes extra memory resources, and may not inlined , so if you may implement your source without std::function, don't use std::function. See, How is std::function implemented?
Also, Lambda to std::function conversion performance

callback in C++ struct

I have been trying to implement a callback function in c++. Within a class, I have a struct, a number of methods, and a method that creates an instance of the struct with one of the other methods as its argument.
The struct has many other variables, but an illustration is depicted here:
class MYCLASS
{
public:
MYCLASS();
struct TEST{
std::function<int(int)> foo;
};
int plus(int x){
return x + 1;
}
int minus(int x){
return x - 1;
}
void sim(){
TEST T; // make an instance of TEST
T.foo = plus(5); // assign TEST.foo a function (plus or minus)
T.foo(); // call the method we assigned
}
};
Within the sim method, I want to create an instance of test and give it either plus or minus, depending on some criterion. Both lines where I try and give the instance T a plus function and subsequently call it are incorrect.
If you want to delay the call to T.foo, then you could use a lambda like this:
T.foo = [this](int x) { return plus(x); };
T.foo(5);
Option - 1
If the member functions plus() and minus() are simple enough like you have shown, you can make them as lambda functions inside the struct TEST.
Since the capture-less lambdas can be stored in typed function pointers, the following will do what you want.
See live demo
#include <iostream>
class MYCLASS
{
int m_var = 5; // just for demonstration
public:
MYCLASS() = default;
struct TEST
{
using fPtrType = int(*)(int); // function pointer type
const fPtrType foo1 = [](int x) { return x + 1; }; // plus function
const fPtrType foo2 = [](int x) { return x - 1; }; // minus function
};
void sim()
{
TEST T;
std::cout << "Answer from int PLUS(int): " << T.foo1(m_var) << std::endl;
std::cout << "Answer from int MINUS(int): " << T.foo2(m_var) << std::endl;
}
};
Option - 2
If the above alter a lot in your code, use typed function pointer again for member functions and do as follows; which will avoid unnecessary copying(by capturing) the class instance to the lambda and template instantiation and other performance issues comes along with std::function as well.
See live demo
#include <iostream>
class MYCLASS
{
using fPtrType = int(MYCLASS::*)(int); // class member function pointer type
public:
MYCLASS() = default;
struct TEST { fPtrType foo = nullptr; };
int plus(int x) { return x + 1; }
int minus(int x) { return x - 1; }
void sim()
{
TEST T;
T.foo = &MYCLASS::plus; // now you can
std::cout << "Answer from int PLUS(int): " << (this->*T.MYCLASS::TEST::foo)(5) << std::endl;
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ syntax would be a bit ugly
// later same ptr variable for minus()
T.foo = &MYCLASS::minus;
int answer = (this->*T.MYCLASS::TEST::foo)(5);
std::cout << "Answer from int MINUS(int): " << answer << std::endl;
}
};
int main()
{
MYCLASS obj;
obj.sim();
return 0;
}
Output:
Answer from int PLUS(int): 6
Answer from int MINUS(int): 4

Passing an inherited method to another method

I am trying to build a class that has a member function with a method as argument. The methods are defined in inherited classes. I build a minimal example:
#include <iostream>
struct base
{
base() {}
int number(int (*f)(int))
{
return f(1);
}
};
struct option1 : base
{
int timesTwo(int i){return 2*i;}
option1()
{
std::cout << number(timesTwo);
}
};
struct option2 : base
{
int timesThree(int i){return 3*i;}
int timesFour (int i){return 4*i;}
option2()
{
std::cout << number(timesThree);
}
};
int main()
{
option1 a; //I would expect this to print "2"
}
The current syntax in the function number is for a general function, but I cannot get it to work for a method of any inherited classes.
The problem here is that you're passing a pointer to a member function, which is completely different from a pointer to a non-member function (which is what your number function takes as an argument).
You could use std::function and std::bind:
int number(std::function<int(int)> f)
{
return f(1);
}
...
number(std::bind(&option1::timesTwo, this, _1));
You could also use templates, and extra arguments, like
template<typename T>
int number(T* object, int(T::*f)(int))
{
return (object->*f)(1);
}
...
number(this, &option1::timesTwo);
Or the simple (but not always correct, depending on situation and use case): Make the callback-function static:
static int timesTwo(int i){return 2*i;}
My recommendation is that you look over the solution using std::function, because then it's easy to call the number function with any type of callable object, like a lambda:
number([](int x){ return x * 2; });
The given error says :
error: reference to non-static member function must be called
You can just add static before your method members.
And I would suggest you to use std::function instead of pointer functions.
A working code :
#include <iostream>
#include <functional>
struct base
{
base() {}
int number(std::function<int(int)> f)
{
return f(1);
}
};
struct option1 : base
{
static int timesTwo(int i){return 2*i;}
option1()
{
std::cout << number(timesTwo);
}
};
struct option2 : base
{
static int timesThree(int i){return 3*i;}
static int timesFour (int i){return 4*i;}
option2()
{
std::cout << number(timesThree);
}
};
int main()
{
option1 a; // now it works
}