Passing a function as a class field - c++

I have a class(Foo) with a function pointer(fun) as one of its fields. I'm trying to pass a pointer to another function to the class' function pointer so I'll be able to call the outer function using a class method.
#include <functional>
class Foo{
private:
std::function<int(int)>* fun();
public:
Foo(std::function<int(int)>* fun()){
this->fun = fun; //Error: function as left operand
}
void UltraFun(){
this->fun();
}
};
int abc(int x){
//blah blah blah
}
int main(){
Foo f = Foo(&abc)
}
Basically, abc's address should be passed as a parameter in Foo's constructor and assigned to its fun pointer to function. Therefore, whenever I call UltraFun(), abc should be called. But the error I get is in "this->fun = fun" that the left operand is a function.

With
std::function<int(int)>* fun();
you declare fun to be a function that takes no arguments and returns a std::function<int(int)>*. That is probably not what you want.
What you probably want is
std::function<int(int)>* fun;
which makes fun a variable.
Same with the constructor argument, the argument fun is a function that returns a std::function<int(int)>*.
The above is only part of the problem... While &abc is indeed a pointer to a function, it can't be converted to a pointer to a std::function<int(int)>. But it can be used to initialize a std::function<int(int)> object.
You need to make the argument and member variable to not be pointers:
std::function<int(int)> fun;
and
Foo(std::function<int(int)> fun);
Lastly you don't call the function correctly, since it should take an int argument.
You need to pass an argument when calling it:
this->fun(123); // Or some other value

You seem to have some confusion about std::function and function pointers.
std::function<int(int)> * fun(); at class scope declares a function that takes no arguments and returns a std::function<int(int)>*.
std::function<int(int)>* fun() as a function parameter is a function pointer variable (named fun) that points to a function taking nothing and returning a std::function<int(int)>*.
Let's replace std::function<int(int)> with double for clarity:
double* fun(); at class scope declares a function that takes no arguments and returns a double*.
double* fun() as a function parameter is a function pointer variable (named fun) that points to a function taking nothing and returning a double*.
But you do not need to deal with function pointers inside your class at all. std::function does all that for you:
class Foo{
private:
std::function<int(int)> fun;
public:
Foo(std::function<int(int)> fun){
this->fun = fun;
}
void UltraFun(){
this->fun(1); // You must pass an integer!
}
};
https://godbolt.org/z/bW8pq8
std::function<int(int)> can store any function that takes an int and returns an int, you don't need to add more pointers or parentheses or even concern yourself with function pointers. And at no point in this code is it necessary to involve pointers to a std::function.
Note that you intend to deal with a function that takes an int, so you can't just call it without any parameters in UltraFun.
A more limited version without std::function, using function pointers directly instead:
class Foo{
private:
int (*fun)(int);
public:
Foo(int fun(int)){
this->fun = fun;
}
void UltraFun(){
this->fun(1);
}
};
https://godbolt.org/z/JkT9KR

Related

c++ forward variadac function arguments to a class constructor

In C++, is there a way to define a function that takes N number of random arguments (number and parameter types could be anything) and in that function, instantiates a class who's constructor expects those arguments. In pseudo-code, something like:
class ClassType {
ClassType(int, string){}
};
void func(Args ...) {
ClassType A(Args);
}
And better yet, define a function pointer for "func"
Yes it is possible. Output of this
#include <iostream>
#include <utility>
struct ClassType {
ClassType(int a, std::string b){
std::cout << a << b;
}
};
template <typename...Args>
void func(Args&& ... args) {
ClassType A(std::forward<Args>(args)...);
}
int main() {
func(12,std::string("foo"));
}
is
12foo
However, it isnt quite clear why you want func to be variadic when ClassTypes constructor only accepts int,string. Calling func with any other combination will fail.
And better yet, define a function pointer for "func"
You cannot have a function pointer to a template (you also cannot have a function pointer to a whole set of overloads). Thats not how function pointers work. What you can do is taking a function pointer to one particular instantiation of func:
auto fptr = &func<int,std::string>;
If you need some function like object that you can pass around then you can use a generic lambda instead of a bare function pointer (since C++17 I believe):
auto flamb = [](auto&&...args){ func(std::forward<decltype(args)>(args)...); };
This works because the lambda is of some type (albeit unnamed and unspecified) and only its operator() is templated. Hence you can pass such lambda around and only when actually calling it the respective operator() is instantiated. Though, also with that you can only call it with the right parameters (int and std::string).

pass a function pointer between classes

I have two claces.
here is the first one
class one{
one(){ }
public:
void change(double a){
//print a
}
void run(){
two tw;
tw->functionpointer=&change;
}
};
and here is the two class
public two{
two();
static void progresschange(double v){
functionpointer(v);
}
public:
void (*functionpointer)(double);
};
as you see in example I have a function in class one, I want to call it from an static function in class two As progresschange is static I can only call change function in class one uisng function pointers. but It does not work and compiles says
error: cannot convert ‘void (one::*)(double)’ to ‘void (*)(double)’ in assignment
it happens in this line
tw->functionpointer=&change;
how can I make it work. it is even possible to pass a function using its function pointer to another class using this method?
thanks
The error message is quite straightforward:
error: cannot convert void (one::*)(double) to void (*)(double) in assignment
void one::change(double) is a member function of the class one, not just a function. Therefore, you can't assign a pointer to this member function (i.e.: void (one::*)(double)) to a pointer to a function with the same signature (i.e.: to a void (*)(double)).
Besides, a non-static member function (like one::change() above) has to be called on an object, so you also need to provide an one object to call that pointed-to non-static member function.
Basically, you can achieve what you want by adding the following data members in two:
void (one::*mem_func_ptr)(double);
one *obj_ptr;
That is, a pointer to the member function (mem_func_ptr) and a pointer to the object to call this member function on (obj_ptr).
To assign to the member function pointer:
mem_func_ptr = &one::change;
Then, to call the member function pointed by mem_func_ptr on the object pointed by obj_ptr with 0.0 as argument:
(obj_ptr->*mem_func_ptr)(0.0);
It can be done analogously by keeping a copy of an object one as data member instead of a ponter. In that case you should use the operator .* instead of ->*.
The problem is that one::change() is a class member so you need to pass a pointer to a class instance as well.
The modern way to do it is to use std::function, std::bind and std::mem_fn:
class two {
....
std::function<void(double)> functionpointer;
}
tw->functionpointer = std::bind(std::mem_fn(&one::change), _1, one_instance);
Alternatively you can use a lambda function:
tw->functionpointer = [&one_instance](double x) { one_instance->change(x); }

C++ pointer to a function

In my code I would like to call different functions by the same name. So I used pointers, and I did work with static functions, now I would like to do the same with non-static functions and it doesn't work at all.
class Amrorder
: {
public:
....
void (*fkt)(real&, const real);
void fktAcPulse(real &rhoRef, const real y);
void fktAcPulseSol(real &rhoRef, const real y);
...
}
void Amrorder::initData(a)
{
...
switch(method){
case 2://
Amrorder::fkt=&Amrorder::fktAcPulse;
break;
case 222://
Amrorder::fkt=&Amrorder::fktAcPulse1d;
break;
}
...
for(int i=0; i<ng; ++i){
Amrorder::fkt(rhoRef, yRef);
...
}
...
}
The code is quiet big so I hope the part above is enough to understand what I want to do.
Thanks for your time!
It doesn't work because your fkt has type:
void (*)(real&, const real);
and you're trying to assign it to, e.g., &Amrorder::fktAcPulse, which has type:
void (Amrorder::*)(real&, const real);
Notice the difference. The latter is a pointer-to-member function, not just a pointer to function. These have different semantics. A pointer to function can just be called (e.g. fkt(a, b)), but a pointer to member function needs to be called on an object (e.g. (obj.*pm)(a, b)).
For simplicity, since you probably just want "something that I can call with a real& and a const real", you may want to consider the type-erased function object: std::function:
std::function<void(real&, const real)> fkt;
This can be initialized with any callable that matches the arguments, so you can assign it to a free function:
void foo(real&, const real) { ... }
fkt = foo;
A static member function:
struct S { static void bar(real&, const real) { ... } };
fkt = &S::bar;
Or a member function, as long as its bound:
fkt = std::bind(&Amrorder::fktAcPulse, this);
fkt = [this](real& a, const real b){ return this->fktAcPulse(a, b); };
The key is that you need an instance of Amrorder to call fktAcPulse, and using std::function lets you use either std::bind or a lambda to store that instance in with the functor itself.
The type of fkt declares a function pointer to a free-standing function or a static member function. But you want to assign a non-static member function pointer to it. So fkt needs to be of the type of a non-static member function pointer of class Amrorder. That type is spelled
void (Amrorder::*fkt)(real&, const real);
// ^^^^^^^^^^
When invoking a function pointer to a non-static member function, you need to specify on which object you want the member to be called (which normally defaults to this when calling a member function directly with its name).
The syntax for this is quite strange. It requires another pair of parentheses and depends on wether you call it on a pointer or an object itself:
(object.*functionPointer)(arguments);
(pointer->*functionPointer)(arguments);
So if you just want to call the function on the this pointer, you need to write
(this->*fkt)(rhoRef, yRef);
(Note that you don't need to specify the class in your code everywhere. Amrorder:: can be removed in front of every function name inside the definition of a member function of the same class.)
When you call a non-static method of a class, the compiler needs to know which instance of the class you want to execute against. So there is a hidden parameter in the call, which is a pointer to the instance.
So you need to write something like this:
Amrorder::fkt=bind( &Amrorder::fktAcPulse, this );

Function pointer as parameter in a class method declaration

I'm trying to make a class method that takes a function pointer (regular C function pointer, not a class method pointer) as a parameter. The only thing that comes up when I search is how to create/use a member function pointer, which I'm NOT trying to do. So here's a method that takes a function pointer that returns a bool and takes two ints as parameters:
class ExampleA
{
public:
void sort(WHAT_GOES_HERE); // Should it be the same as method definition below?
};
ExampleA::sort(bool (*customSort)(int, int)) // Hopefully this is correct
{
// Use function pointer
}
Is there a way to declare the parameter in the method declaration without naming it like a method with an int parameter?
class ExampleB
{
public:
void someFunction(int); // Not named here
};
ExampleB::someFunction(int varName)
{
// do whatever
}
Yep! Just leave out the name.
void sort(bool (*)(int, int));
bool (*)(int, int)
Basically, remove the name of the variable to get a declaration without a variable name.
However, you are often better off with a typedef:
typedef bool(*custom_sorter)(int, int);
class ExampleA {
public:
void sort(custom_sorter);
};
ExampleA::sort(custom_sorter customSort) {
// Use function pointer
}
which is equivalent.
As I personally hate the syntax to declare a function pointer, in C++11 I might do:
template<class T> using type=T;
...
void sort(type<bool(int,int)>*)
which puts the signature type together, then I put a * after it to make it a pointer.
But I'm strange.
The declaration should match the definition, so WHAT_GOES_HERE should be bool (*customSort)(int, int), and also the function definition should have the return type void specified.
You can optionally leave out the name customSort, it makes no difference.
This is somewhat inflexible; consider making it a function template that accepts a functor or a std::function instead of a function pointer; then your callers can call it with a wider range of functions.

Can I pass a member function of a class as a function parameter?

So I have a function in C++ which takes in another function:
double integral(double (*f)(double x){...};
I also have a class which has a member function f:
class Test{
public:
double myfun(double x){...};
};
I want to be able to call the integral function using the member function myfun of class Test. Is there a way to do this? For example, is it possible to do the following:
Test A;
integral(A.myfun);
I would even like to take this further and call integral within class Test, using its own member function as input!
Thanks!
No; an ordinary function pointer cannot store the address to a non-static member function. Here are two solutions you might consider.
1) Make myfun static. Then integral(A::myfun) should compile.
2) If you have C++11 support, make the integral function take a general functor type,
template<typename Functor>
double integral(Functor f) { ... };
and bind an instance of Test to create a function object that only takes a double as an argument,
Test A;
integral(std::bind(&Test::myfun, A, std::placeholders::_1));
or simply pass a lambda,
Test A;
integral([&A](double x){ return A.myfun(x); });