I have this example code of using pointer to member function, which I want to change during runtime, but I cannot make it work. I've already tried this->*_currentPtr(4,5) (*this)._currentPtr(4, 5). What is the proper way of calling pointer to method inside same class ?
The error : expression must have (pointer-to-) function type
#include <iostream>
#include <cstdlib>
class A {
public:
void setPtr(int v);
void useFoo();
private:
typedef int (A::*fooPtr)(int a, int b);
fooPtr _currentPtr;
int foo1(int a, int b);
int foo2(int a, int b);
};
void A::setPtr(int v){
if(v == 1){
_currentPtr = foo1;
} else {
_currentPtr = foo2;
}
}
void A::useFoo(){
//std::cout << this->*_currentPtr(4,5); // ERROR
}
int A::foo1(int a, int b){
return a - b;
}
int A::foo2(int a, int b){
return a + b;
}
int main(){
A obj;
obj.setPtr(1);
obj.useFoo();
return 0;
}
You need to tell the compiler which class the foos are coming from (otherwise it thinks they're functions from global scope):
void A::setPtr(int v){
if(v == 1){
_currentPtr = &A::foo1;
// ^^^^
} else {
_currentPtr = &A::foo2;
// ^^^^
}
}
and you need a set of parentheses here:
std::cout << (this->*_currentPtr)(4,5);
// ^ ^
Related
If I have a friend function can I somehow use set() to assign a value to a private variable inside the function? Or some other method?
Example : Here I have 3 private variables. I tried to make the sum of 2 of them and store the result in the 3rd one. I tried to do it with a setter but the result is 0. In main it works, but I don't know if I can make it work in the class function.
#include <iostream>
using namespace std;
class Function{
private:
int a;
int b;
int sum;
public:
Function() = default;
Function(int _a, int _b);
friend int sumNumber(Function f);
//Setter and getter
int getA() const;
void setA(int a);
int getB() const;
void setB(int b);
int getSum() const;
void setSum(int sum);
};
Function::Function(int _a, int _b) {
this->a = _a;
this->b = _b;
}
int Function::getA() const {
return a;
}
void Function::setA(int a) {
Function::a = a;
}
int Function::getB() const {
return b;
}
void Function::setB(int b) {
Function::b = b;
}
int Function::getSum() const {
return sum;
}
void Function::setSum(int sum) {
Function::sum = sum;
}
int sumNumber(Function f) {
int a = f.getA();
int b = f.getB();
int sum = a + b;
f.setSum(sum);
return sum;
};
int main() {
Function AA(1,2);
cout << sumNumber(AA);
cout << " " << AA.getSum();
AA.setSum(sumNumber(AA));
cout << "\n" << AA.getSum();
return 0;
}
Output :
3 0
3
As alluded to in the comments, the issue is with this function:
int sumNumber(Function f) {
int a = f.getA();
int b = f.getB();
int sum = a + b;
f.setSum(sum);
return sum;
};
Let us walk through your code:
Function AA(1,2);
You create a object of type Function, called AA and you allocate each member variable of that object via the constructor (1 and 2).
cout << sumNumber(AA);
You call your method (sumNumber) and pass to it a copy of your variable AA. That function adds the two numbers together and internally calls setSum.
cout << " " << AA.getSum();
You now try to display the sum value by calling the getSum method. But the issue was that you passed a copy of your variable into the sumNumber function. The original AA variable was left alone.
To fix this you need to adjust your function by adding an ampersand &. Like this:
int sumNumber(Function& f) {
int a = f.getA();
int b = f.getB();
int sum = a + b;
f.setSum(sum);
return sum;
};
Now your variable AA is being passed by reference and not by value. There are lots of tutorials about this concept.
I'm trying to make this code work:
#include <iostream>
using namespace std;
int f(int x) {
return x+1;
}
class A {
public:
int g(int y);
};
int A::g(int y) = f;
int main() {
A test;
cout << test.g(3) << endl;
return 0;
}
It does not compile because of the line int A::g(int y) = f;.
What is the correct way to achieve that an external function can be used as a method?
You can use a pointer to function as a member of class A. Now assign function f to g member of A.
int f(int x) {
return x+1;
}
class A {
public:
int (*g)(int);
};
int main(){
A test;
test.g = f;
cout << test.g(10); // prints 11
}
You can accomplish the same by making your function a callable objects by implementing () operator. so you can have that as member of the class, and then it can normally be used as function on the class objects.
#include <iostream>
struct do_something{
int operator()(int num){
return num;
}
};
class test{
int sum;
public:
do_something fun;
};
int main(){
test obj;
std::cout << obj.fun(10);
}
How do I properly pass member function as a parameter?
MyCode:
#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 (*funcPtr)(int a, int b);
int myFunc(funcPtr 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;
}
};
int main()
{
Test test;
test.setup();
}
Result:
Error: Cannot initialize a parameter of type 'Test::funcPtr' (aka 'int
()(int, int)') with an rvalue of type 'int (Test::)(int, int)'
Expected Result:
8
2
Your methods should be "regular" functions. add static to them to allow to use them with function pointers:
class Test
{
public:
static int add(int a, int b)
{
return a + b;
}
static int sub(int a, int b)
{
return a - b;
}
// ...
};
If you really pointer on method, you should replace int (*funcPtr)(int a, int b) by int (Test::*funcPtr)(int a, int b) and use something like that instead:
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;
}
};
You should read about std:: function and std::bind. The first thing will allow you to store a function pointer with multiple form (Functor, lamda, binded), and the second will allow you to bind parameters to your function call (In your case, you want to bind the instance of the class that is needed to call your function).
std:: function<int(int, int)> func = std::bind(&Class::Method, instancePtr, std::placeholders::_1, std:: placeholders::_2);
int result = func(a, b);
However, in your context, your methods should be marked as static (They are not using any non-static member of your class), but the example and the explanation I provided answer to your base question
Firstly, based on your question the best solution here will be without using the pointer instead declare your methods as static and call them directly as given below.
That solution will generate the right results without using the complexity of pointers.
Simple is better if you do not need to use pointers it is better to not use them. code will be more readable as well.
Following code works i tested it:
#include <iostream>
using namespace std;
class Test
{
public:
static int add(int a, int b)
{
return a + b;
}
static int sub(int a, int b)
{
return a - b;
}
void setup()
{
cout << add( 5, 3) << endl;
cout << sub(5, 3) << endl;
}
};
int main()
{
Test test;
test.setup();
}
For example, I have a class
struct A {int a; bool b;};
And I want to generate a template function to get its elements (like the std::get to get a tuple element)
template<unsigned i, class T>
auto Get(T& t);
template<>
int& Get<0, A>(A& a)
{
return a.a;
}
template<>
bool& Get<1, A>(A& a)
{
return a.b;
}
int main()
{
A a;
Get<0>(a) = 10;
Get<1>(a) = true;
return 0;
}
The above code doesn't work. The challenge is that I don't know the returned type of Get for arbitrary class. Any way to implement it? Thanks.
Assuming you wouldn't mind making this in a "manual manner" you can do this really simply.
#include <tuple>
struct A {
int a; bool b;
};
template<size_t N>
auto get(A& a) -> decltype(std::get<N>(std::tie(a.a, a.b))) {
return std::get<N>(std::tie(a.a, a.b));
}
#include <iostream>
int main() {
A a;
get<0>(a) = 10;
get<1>(a) = true;
std::cout << a.a << '\n' << a.b;
}
Output:
10
1
This is related to this previous question: Using boost::bind with boost::function: retrieve binded variable type.
I can bind a function like this:
in .h:
class MyClass
{
void foo(int a);
void bar();
void execute(char* param);
int _myint;
}
in .cpp
MyClass::bar()
{
vector<boost::function<void(void)> myVector;
myVector.push_back(boost::bind(&MyClass::foo, this, MyClass::_myint);
}
MyClass::execute(char* param)
{
boost::function<void(void)> f = myVector[0];
_myint = atoi(param);
f();
}
But how can I bind a return value ? i.e.:
in .h:
class MyClass
{
double foo(int a);
void bar();
void execute(char* param);
int _myint;
double _mydouble;
}
in .cpp
MyClass::bar()
{
vector<boost::function<void(void)> myVector;
//PROBLEM IS HERE: HOW DO I BIND "_mydouble"
myVector.push_back(boost::bind<double>(&MyClass::foo, this, MyClass::_myint);
}
MyClass::execute(char* param)
{
double returnval;
boost::function<void(void)> f = myVector[0];
_myint = atoi(param);
//THIS DOES NOT WORK: cannot convert 'void' to 'double'
// returnval = f();
//MAYBE THIS WOULD IF I COULD BIND...:
// returnval = _mydouble;
}
If what you want is a nullary function that returns void but assigns a value to _myDouble with the result of foo() before doing so, then you cannot do this easily with just Boost.Bind. However, Boost has another library specifically catered to this sort of thing -- Boost.Phoenix:
#include <iostream>
#include <vector>
#include <boost/function.hpp>
#include <boost/phoenix/phoenix.hpp>
struct MyClass
{
MyClass() : _myVector(), _myInt(), _myDouble() { }
void setMyInt(int i);
void bar();
void execute();
private:
double foo(int const a) { return a * 2.; }
std::vector<boost::function<void()> > _myVector;
int _myInt;
double _myDouble;
};
void MyClass::setMyInt(int const i)
{
_myInt = i;
}
void MyClass::bar()
{
using boost::phoenix::bind;
_myVector.push_back(
bind(&MyClass::_myDouble, this) =
bind(&MyClass::foo, this, bind(&MyClass::_myInt, this))
);
}
void MyClass::execute()
{
if (_myVector.empty())
return;
_myVector.back()();
double const returnval = _myDouble;
std::cout << returnval << '\n';
}
int main()
{
MyClass mc;
mc.bar();
mc.setMyInt(21);
mc.execute(); // prints 42
mc.setMyInt(3);
mc.execute(); // prints 6 (using the same bound function!)
// i.e., bar has still only been called once and
// _myVector still contains only a single element;
// only mc._myInt was modified
}
problem 1: myVector needs to be a class member.
problem 2: myVector is interested in functions that return doubles and take no arguments, which would be boost::function<double()>
then, to bind _mydouble to the parameter of foo, call boost::bind(&MyClass::foo, this, MyClass::_mydouble) which should give you a compilation warning about casting a double to an int for when foo is called.
The closest you can come with Boost.Bind is providing the toreturn as a parameter.
#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
using namespace std;
class Foo {
int myInt;
double myDouble;
public:
Foo() : myInt(3), myDouble(3.141592) { }
void SetToMyInt(double& param)
{
param = myInt;
}
void SetToMyDouble(double& param)
{
param = myDouble;
}
double Execute()
{
double toReturn = 2;
boost::function<void(double&)> f = boost::bind(&Foo::SetToMyDouble, this, _1);
f(toReturn);
return toReturn;
}
};
int main() {
Foo foo;
std::cout << foo.Execute() << std::endl;
return 0;
}