How to pass lamda as a function pointer argument of member function? - c++

I learned how to pass member functions to another member function as a function pointer argument.
Now, I'm trying to pass lamda as a function pointer argument of member function.
My Code:
#include <iostream>
using namespace std;
class Test
{
public:
int add(int a, int b)
{
return a + b;
}
int sub(int a, int b)
{
return a - b;
}
typedef int (Test::*funcPtr)(int a, int b);
int myFunc(funcPtr func, int a, int b)
{
return (this->*func)(a, b);
}
void setup()
{
cout << myFunc(&Test::add, 5, 3) << endl;
cout << myFunc(&Test::sub, 5, 3) << endl;
cout << myFunc([](int a, int b) {return a * b;}, 5, 3) << endl; //ERROR!!!
}
};
int main()
{
Test test;
test.setup();
}
Result:
Error: : No viable conversion from lambda to 'Test::funcPtr' (aka 'int
(Test::*)(int, int)')
Expected Result:
8
2
15
How should I correct my code so I can get the expected result?

one option is making your functions static and then use std::function as type:
using funcType = std::function<int(int, int)>;
int myFunc(funcType func, int a, int b)
{
return func(a, b);
}
void setup()
{
cout << myFunc(Test::add, 5, 3) << endl;
cout << myFunc(Test::sub, 5, 3) << endl;
cout << myFunc([](int a, int b) {return a * b;}, 5, 3) << endl;
}
Live
Thanks to #holyBlackCat the other option is using regular function pointer(member functions need to be static):
typedef int (*funcPtr)(int a, int b);
//or:
//using funcPtr = int (*)(int a, int b);
int myFunc(funcPtr func, int a, int b)
{
return (*func)(a, b);
}
and also template:
template<typename funcType>
int myFunc(funcType func, int a, int b)
{
return func(a, b);
}
void setup()
{
cout << myFunc(Test::add, 5, 3) << endl;
cout << myFunc(Test::sub, 5, 3) << endl;
cout << myFunc([](int a, int b) {return a * b;}, 5, 3) << endl;
}
regular function pointer live, template live
EDIT
The examples provided above are working only with static member function. To invoke non-static member functions you can use pointer to member function type
using funcPtr = int(Test::*)(int a, int b);
int myFunc(funcPtr func, int a, int b)
{
return invoke(func, this, a, b);
}
//..
// call:
cout << myFunc(&Test::add, 5, 3) << endl;
pointer to non-static member function live

Related

C structure object member name as parameter

How can I pass a structure name, object name, different member name(whose value to be verified) as a parameter to a function ?
struct st{
int a;
int b;
}
bool verify(____ st , ____ b){
if(obj.b == 5)return true;
return false;
}
int main(){
st obj;
// now that I know all the names of members of struct name
// HOW can I verify passing different member name as parameter
cout<<verify(__,__);
}
For an instance:
(example with error)
#include<iostream>
using namespace std;
struct st{
int a;
int b;
};
bool verify(st obj, st.a val){
if(obj.a==val)
return true;
}
int main()
{
cout<<"Hello World"<<endl;
st obj;
cout<<verify(obj,a);
//cout<<verify(obj,b);
return 0;
}
You can use a pointer to data member:
bool verify(const st &obj, int st::* field) {
return obj.*field == 5;
}
...
st obj;
std::cout << verify(obj, &st::a);
std::cout << verify(obj, &st::b);
But the syntax is confusing and just passing a reference to the data member to verify is easier:
bool verify(int field) {
return field == 5;
}
...
st obj;
std::cout << verify(obj.a);
std::cout << verify(obj.b);
Using a template:
#include <iostream>
struct st
{
int a;
int b;
};
struct st2
{
int c;
int d;
};
template<typename T>
bool verify(const T &obj, int T::* field)
{
return obj.*field == 5;
}
int main()
{
st obj = {5, 6};
st2 obj2 = {5, 6};
std::cout << verify(obj, &st::a) << "\n"; // 1, since obj.a is 5
std::cout << verify(obj2, &st2::d) << "\n"; // 0, since obj.d is not 5
return 0;
}

Using a function pointer array to call a method of a class

I would like to write a program in C++ which contains an array of function pointers.
Here is the code:
#include <iostream>
using namespace std;
class MyClass {
int a, b;
public:
MyClass(int i, int j) : a(i), b(j) {}
int add() { return a + b; }
int sub() { return a - b; }
};
void func(int (MyClass::* funcPtr[])(), MyClass& a, int i) {
if (i == 0) {
funcPtr[i] = &MyClass::add;
funcPtr;
}
if (i == 1) {
funcPtr[i] = &MyClass::sub;
funcPtr;
}
cout << " Result: " << (a.*funcPtr[i])() << endl;
}
int main(){
int auswahl = 0;
int i = 4, j = 5;
cout << "Which function? [0]-Add [1]-Substract\n";
cin >> select;
MyClass a(i,j);
func(NULL, a, select);
}
After playing around a lot I got the program to compile successfully. But it throws "Write Access Violation" on running.
The problem seems to be related to:
funcPtr[i] = &MyClass::add;
funcPtr[i] = &MyClass::sub;
It'd be very nice, if you could help me solve the problem.
Thank you so much and have a happy time!
As you pass NULL or nullptr in your function, so this line:
funcPtr[i] = &MyClass::add;
Is writing at index i into a null array!
You'd have to provide an array for your function to write into:
MyClass a(i,j);
int (MyClass::* funcPtr[2])();
func(funcPtr, a, select);
Note that using std::array instead of c-style array would avoid this problem, since they are not nullable:
void func(std::array<int (MyClass::*)(), 2> funcPtr, MyClass& a, int i) {
// ...
}
// ...
std::array<int (MyClass::*)(), 2> funcPtr;
func(funcPtr /* cannot pass null */, a, i);

Getting an error "invalid use of non-static data member 'stu::n' "

#include <bits/stdc++.h>
using namespace std;
struct stu {
int n;
stu(int _n = 0):n(_n) { }
int add(int a, int b = n-1) {
return a + b;
}
};
int main() {
stu obj = stu(5);
cout << obj.add(10) << endl;
}
The compiler shows the message " invalid use of
non-static data member 'stu::n' ".
What is wrong with this code. Any help would be great.
Thanks.
You can't use default arguments this way. Consider writing two separate functions:
struct stu {
int n;
int add(int a, int b) { return a + b; }
int add(int a) { return a + n - 1; }
}

function pointers generate 'invalid use of non-static member function' error

I am trying to grasp pointer function concept in a better way. So I have a very simple and working example as:
#include <iostream>
using namespace std;
int add(int first, int second)
{
return first + second;
}
int subtract(int first, int second)
{
return first - second;
}
int operation(int first, int second, int (*functocall)(int, int))
{
return (*functocall)(first, second);
}
int main()
{
int a, b;
int (*plus)(int, int);
int (*minus)(int, int);
plus = &add;
minus = &subtract;
a = operation(7, 5, add);
b = operation(20, a, minus);
cout << "a = " << a << " and b = " << b << endl;
return 0;
}
So far so good,
Now I need to group the functions in a class, and select add or subtract based on the function pointer that i use. So I just make a small modification as:
#include <iostream>
using namespace std;
class A
{
public:
int add(int first, int second)
{
return first + second;
}
int subtract(int first, int second)
{
return first - second;
}
int operation(int first, int second, int (*functocall)(int, int))
{
return (*functocall)(first, second);
}
};
int main()
{
int a, b;
A a_plus, a_minus;
int (*plus)(int, int) = A::add;
int (*minus)(int, int) = A::subtract;
a = a_plus.operation(7, 5, plus);
b = a_minus.operation(20, a, minus);
cout << "a = " << a << " and b = " << b << endl;
return 0;
}
and the obvious error is:
ptrFunc.cpp: In function ‘int main()’:
ptrFunc.cpp:87:29: error: invalid use of non-static member function ‘int A::add(int, int)’
ptrFunc.cpp:88:30: error: invalid use of non-static member function ‘int A::subtract(int, int)’
coz I haven't specified which object to invoke(and I don't want to use static methods for now)
EDIT:
several comments and answers suggested that the non-static version(as I have written) is not possible.(thanks to all)
So,
Modifying the class in the following manner also wont work:
#include <iostream>
using namespace std;
class A
{
int res;
public:
A(int choice)
{
int (*plus)(int, int) = A::add;
int (*minus)(int, int) = A::subtract;
if(choice == 1)
res = operation(7, 5, plus);
if(choice == 2)
res = operation(20, 2, minus);
cout << "result of operation = " << res;
}
int add(int first, int second)
{
return first + second;
}
int subtract(int first, int second)
{
return first - second;
}
int operation(int first, int second, int (*functocall)(int, int))
{
return (*functocall)(first, second);
}
};
int main()
{
int a, b;
A a_plus(1);
A a_minus(2);
return 0;
}
generated this error:
ptrFunc.cpp: In constructor ‘A::A(int)’:
ptrFunc.cpp:11:30: error: cannot convert ‘A::add’ from type ‘int (A::)(int, int)’ to type ‘int (*)(int, int)’
ptrFunc.cpp:12:31: error: cannot convert ‘A::subtract’ from type ‘int (A::)(int, int)’ to type ‘int (*)(int, int)’
may I know how to solve this issue please?
thanks
The syntax to declare a function pointer to member methods is:
int (A::*plus)(int, int) = &A::add;
int (A::*minus)(int, int) = &A::subtract;
To invoke member methods use .* or ->* operator:
(a_plus.*plus)(7, 5);
Also have a look at http://msdn.microsoft.com/en-us/library/b0x1aatf(v=vs.80).aspx
Hope this helps.
Complete code:
#include <iostream>
using namespace std;
class A
{
public:
int add(int first, int second)
{
return first + second;
}
int subtract(int first, int second)
{
return first - second;
}
int operation(int first, int second, int (A::*functocall)(int, int))
{
return (this->*functocall)(first, second);
}
};
int main()
{
int a, b;
A a_plus, a_minus;
int (A::*plus)(int, int) = &A::add;
int (A::*minus)(int, int) = &A::subtract;
a = a_plus.operation(7, 5, plus);
b = a_minus.operation(20, a, minus);
cout << "a = " << a << " and b = " << b << endl;
return 0;
}
You can't pass non-static member function as argument that easy. And for your needs, I believe it's better to override operators: http://www.learncpp.com/cpp-tutorial/92-overloading-the-arithmetic-operators/
But if you really need them as actual member functions - just make them static.
The edit you made to your code is still wrong because it doesn't make the member functions static. You need to make the add, subtract etc. functions static by adding the static specifier:
#include <iostream>
using namespace std;
class A
{
int res;
public:
A(int choice)
{
int (*plus)(int, int) = A::add;
int (*minus)(int, int) = A::subtract;
if(choice == 1)
res = operation(7, 5, plus);
if(choice == 2)
res = operation(20, 2, minus);
cout << "result of operation = " << res;
}
static int add(int first, int second)
{
return first + second;
}
static int subtract(int first, int second)
{
return first - second;
}
static int operation(int first, int second, int (*functocall)(int, int))
{
return (*functocall)(first, second);
}
};
See the below code. The function calls are working without making them static.
class A
{
public:
int add(int first, int second)
{
return first + second;
}
int subtract(int first, int second)
{
return first - second;
}
int operation(int first, int second, int(A::*functocall)(int, int))
{
return (this->*functocall)(first, second);
}
};
//typedef int(A::*PFN)(int, int) ;
int main()
{
int a, b;
A a_plus, a_minus;
a = a_plus.operation(7, 5, &A::add);
b = a_minus.operation(20, a, &A::subtract);
cout << "a = " << a << " and b = " << b << endl;
return 0;
}

extended GCD algorithm

i have wrote following algorith for extended GCD algorithm,just dont know how to return triple and could anybody help me?
#include<iostream>
#include<math.h>
using namespace std;
int gcd(int a,int b) { return (b==0 ?a:gcd(b,a%b));}
long long gcd(long a,long b) { return (b==0 ?a:gcd(b,a%b));}
template<class Int> Int gcd(Int a,Int b) { return (b==0 ?a:gcd(b,a%b));}
template<class Int>
struct Triple
{
Int d,x,y;
Triple(Int q,Int w,Int e) :d(q),x(w),y(e)) {}
};
//extended GCD
/* computes d=gcd(a,b)
also x and y such that d=a*x+y*b and return tripls (d,x,y)
*/
template<class Int>
Triple <Int> egcd(Int a,Int b) {
if(!b) return Triple<Int>(a,Int(1),Int(0));
Triple<int>q=egcd(b,a%b);
return Triple<Int>(q.d,q.y,q.x-a/b*q.y);
}
int main(){
int a=35;
int b=13;
return 0;
}
how to finish it using my triple struct constructor?please help me
(1) Correct the constructor, it does not compile (remove one bracket):
Triple(Int q,Int w,Int e) : d(q), x(w), y(e) {}
(2) In main() call:
Triple <int> t = egcd(a, b);
cout << t.d << ", " << t.x << ", " << t.y << endl;