assign a member function to a function pointer [duplicate] - c++

This question already has answers here:
How can I pass a member function where a free function is expected?
(9 answers)
Closed 2 months ago.
If I have two classes like this :
class A
{
public:
int *(*fun)( const int &t );
A( int *( *f )( const int &t ) ) : fun( f ) {}
};
class B
{
private:
float r;
int *f(const int &t)
{
return new int( int( r ) + t );
}
A a;
B() : a( A( f ) ) {}
};
This results in compiler error.
I want to assign f to a's function pointer.
The thing is that A can be used by many classes not just B so I can't simply define fun as B::*fun.
None of the posts I've found on the internet and here on stackoverflow address the issue of using the function pointers with many classes each having its own member function but the same prototype.
So what to do?

this result in compiler error
Because f is a A's non-static member function returning int*, that accepts single const reference to int. That means, that its type is not:
int* (*)(const int &);
but:
int* (A::*)(const int&);
Also, your code signalizes very bad design - I think you need simple virtual function. But if you want to keep writing things this way, you may want to read: ISOCPP: Pointers to members.
Remember, that non-static member functions of type C always accepts additional implicit argument of type C* (or const C*, if function is declared with const qualifier), that points to instance of C this function was called on.

Your code looks confusing and, personally, I believe that C function pointers look ugly on C++'s OO implementation. So I would advise you to use the std::function. It only has been available since C++11. If you cannot use it, try looking on Boost's Implementation.
I can give you an example of how to use the std::function:
bool MyFunction(int i)
{
return i > 0;
}
std::function<bool(int)> funcPointer = MyFunction;
Using this you will drastically improve your code reliability. As of your problem, specifically:
class A
{
public:
std::function<int*(const int&)> fun;
A(std::function<int*(const int&)> f) : fun(f) {}
};
class B
{
private:
float r;
int *f(const int &t)
{
return new int(int(r) + t);
}
A *a;
B()
{
std::function<int*(const int&)> tempFun = std::bind(&B::f, this, _1);
a = new A(tempFun);
}
};
You have to add the following namespace:
using namespace std::placeholders;

So what to do
Not much. Other than templating A on the type of objects for which it will hold a pointer to a member function taking a reference to a const int and returning a pointer to int.
What you're trying to do is to mix a pointer to a free function with a pointer to member function. Whilst it sounds like they're both function pointers they're different enough to not be able to pass through the same type definition.

Related

C++ and pointer to function of class [duplicate]

This question already has answers here:
How can I pass a member function where a free function is expected?
(9 answers)
Closed 2 months ago.
If I have two classes like this :
class A
{
public:
int *(*fun)( const int &t );
A( int *( *f )( const int &t ) ) : fun( f ) {}
};
class B
{
private:
float r;
int *f(const int &t)
{
return new int( int( r ) + t );
}
A a;
B() : a( A( f ) ) {}
};
This results in compiler error.
I want to assign f to a's function pointer.
The thing is that A can be used by many classes not just B so I can't simply define fun as B::*fun.
None of the posts I've found on the internet and here on stackoverflow address the issue of using the function pointers with many classes each having its own member function but the same prototype.
So what to do?
this result in compiler error
Because f is a A's non-static member function returning int*, that accepts single const reference to int. That means, that its type is not:
int* (*)(const int &);
but:
int* (A::*)(const int&);
Also, your code signalizes very bad design - I think you need simple virtual function. But if you want to keep writing things this way, you may want to read: ISOCPP: Pointers to members.
Remember, that non-static member functions of type C always accepts additional implicit argument of type C* (or const C*, if function is declared with const qualifier), that points to instance of C this function was called on.
Your code looks confusing and, personally, I believe that C function pointers look ugly on C++'s OO implementation. So I would advise you to use the std::function. It only has been available since C++11. If you cannot use it, try looking on Boost's Implementation.
I can give you an example of how to use the std::function:
bool MyFunction(int i)
{
return i > 0;
}
std::function<bool(int)> funcPointer = MyFunction;
Using this you will drastically improve your code reliability. As of your problem, specifically:
class A
{
public:
std::function<int*(const int&)> fun;
A(std::function<int*(const int&)> f) : fun(f) {}
};
class B
{
private:
float r;
int *f(const int &t)
{
return new int(int(r) + t);
}
A *a;
B()
{
std::function<int*(const int&)> tempFun = std::bind(&B::f, this, _1);
a = new A(tempFun);
}
};
You have to add the following namespace:
using namespace std::placeholders;
So what to do
Not much. Other than templating A on the type of objects for which it will hold a pointer to a member function taking a reference to a const int and returning a pointer to int.
What you're trying to do is to mix a pointer to a free function with a pointer to member function. Whilst it sounds like they're both function pointers they're different enough to not be able to pass through the same type definition.

What's the function signature of a member function?

I'm having trouble understanding function signatures and pointers.
struct myStruct
{
static void staticFunc(){};
void nonstaticFunc(){};
};
int main()
{
void (*p)(); // Pointer to function with signature void();
p = &myStruct::staticFunc; // Works fine
p = &myStruct::nonstaticFunc; // Type mismatch
}
My compiler says that the type of myStruct::nonstaticFunc() is void (myStruct::*)(), but isn't that the type of a pointer pointing to it?
I'm asking because when you create an std::function object you pass the function signature of the function you want it to point to, like:
std::function<void()> funcPtr; // Pointer to function with signature void()
not
std::function<void(*)()> funcPtr;
If I had to guess based on the pattern of void() I would say:
void myStruct::();
or
void (myStruct::)();
But this isn't right. I don't see why I should add an asterisk just because it's nonstatic as opposed to static. In other words, pointer void(* )() points to function with signature void(), and pointer void(myStruct::*)() points to function with signature what?
To me there seems to be a basic misunderstanding of what a member pointer is. For example if you have:
struct P2d {
double x, y;
};
the member pointer double P2d::*mp = &P2d::x; cannot point to the x coordinate of a specific P2d instance, it is instead a "pointer" to the name x: to get the double you will need to provide the P2d instance you're looking for... for example:
P2d p{10, 20};
printf("%.18g\n", p.*mp); // prints 10
The same applies to member functions... for example:
struct P2d {
double x, y;
double len() const {
return sqrt(x*x + y*y);
}
};
double (P2d::*f)() const = &P2d::len;
where f is not a pointer to a member function of a specific instance and it needs a this to be called with
printf("%.18g\n", (p.*f)());
f in other words is simply a "selector" of which of the const member functions of class P2d accepting no parameters and returning a double you are interested in. In this specific case (since there is only one member function compatible) such a selector could be stored using zero bits (the only possible value you can set that pointer to is &P2d::len).
Please don't feel ashamed for not understanding member pointers at first. They're indeed sort of "strange" and not many C++ programmers understand them.
To be honest they're also not really that useful: what is needed most often is instead a pointer to a method of a specific instance.
C++11 provides that with std::function wrapper and lambdas:
std::function<double()> g = [&](){ return p.len(); };
printf("%.18g\n", g()); // calls .len() on instance p
std::function<void()> funcPtr = std::bind(&myStruct::nonstaticFunc, obj);
Is how you store a member function in std::function. The member function must be called on a valid object.
If you want to delay the passing of an object until later, you can accomplish it like this:
#include <functional>
#include <iostream>
struct A {
void foo() { std::cout << "A::foo\n"; }
};
int main() {
using namespace std::placeholders;
std::function<void(A&)> f = std::bind(&A::foo, _1);
A a;
f(a);
return 0;
}
std::bind will take care of the details for you. std::function still must have the signature of a regular function as it's type parameter. But it can mask a member, if the object is made to appear as a parameter to the function.
Addenum:
For assigning into std::function, you don't even need std::bind for late binding of the object, so long as the prototype is correct:
std::function<void(A&)> f = &A::foo;
p = &myStruct::staticFunc; // Works fine
p = &myStruct::nonstaticFunc; // Type mismatch
Reason : A function-to-pointer conversion never applies to non-static member functions because an lvalue that refers to a non-static member function
cannot be obtained.
pointer void(* )() points to function with signature void(), and pointer void(myStruct::*)() points to function with signature what?
myStruct:: is to make sure that the non-static member function of struct myStruct is called (not of other structs, as shown below) :
struct myStruct
{
static void staticFunc(){};
void nonstaticFunc(){};
};
struct myStruct2
{
static void staticFunc(){};
void nonstaticFunc(){};
};
int main()
{
void (*p)(); // Pointer to function with signature void();
void (myStruct::*f)();
p = &myStruct::staticFunc; // Works fine
p = &myStruct2::staticFunc; // Works fine
f = &myStruct::nonstaticFunc; // Works fine
//f = &myStruct2::nonstaticFunc; // Error. Cannot convert 'void (myStruct2::*)()' to 'void (myStruct::*)()' in assignment
return 0;
}
When you use a pointer, std::function or std::bind to refer to a non-static member function (namely, "method" of class Foo), the first param must be a concrete object of class Foo, because non-static method must be called by a concrete object, not by Class.
More details: std::function and
std::bind.
The answer is in the doc.
Pointer to member declarator: the declaration S C::* D; declares D as
a pointer to non-static member of C of type determined by
decl-specifier-seq S.
struct C
{
void f(int n) { std::cout << n << '\n'; }
};
int main()
{
void (C::* p)(int) = &C::f; // pointer to member function f of class C
C c;
(c.*p)(1); // prints 1
C* cp = &c;
(cp->*p)(2); // prints 2
}
There are no function with signature void (). There are void (*)() for a function or void (foo::*)() for a method of foo. The asterisk is mandatory because it's a pointer to x. std::function has nothing to do with that.
Note: Your confusion is that void() is that same signature that void (*)(). Or even int() <=> int (*)(). Maybe you think that you can write int (foo::*) to have a method pointer. But this is a data member pointer because the parenthesis are optional, int (foo::*) <=> int foo::*.
To avoid such obscure syntax you need to write your pointer to function/member with the return type, the asterisk and his parameters.

How to have local anonymous C++ function object use argument from containing method? [duplicate]

This question already has answers here:
What is a lambda expression in C++11?
(10 answers)
Closed 6 years ago.
What's the correct way to have an anonymous local function object access an argument of the containing method? I.e., what's the correct way to do the following:
void A::foo(B& b)
{
struct {
void operator()() {b.bar();}
} func;
func();
}
NB: This example is contrived for simplicity: the actual use-case involves applying an anonymous local function object to each element in a container to have the element act on the argument of the containing method.
You need to pass the reference/pointer of the worked-on object to the anonymous one. But since it's anonymous, you cannot declare its constructor. If you named it, you'd be able to say:
void A::foo(B& b)
{
struct Foo{
B& b;
Foo(B& b) : b(b) {}
void operator()() {b.bar();}
} func{b};
func();
}
That being said, in C++11 - as you tagged this question - you could use a lambda expression:
void A::foo(B& b)
{
auto func = [&]{ b.bar(); };
func();
}
A function cannot access stuff from its local scope.
Lambdas get around that by capturing variables in their local scope. They copy/move/reference them. But they're not technically accessing those variables. Only lambdas can do this.
You can of course explicitly do what a lambda does implicitly. That is, have the class's constructor take a copy or reference to a variable, then initialize the object by calling that constructor. Of course, that means it cannot be an anonymous class anymore.
In fact you wrote almost all correctly. Here you are
#include <iostream>
struct A
{
void foo( const struct B &b );
};
struct B
{
void bar() const { std::cout << "Hello A!" << std::endl; }
};
void A::foo( const B &b )
{
struct
{
void operator ()( const B &b ) const { b.bar(); }
} func;
func( b );
};
int main()
{
A().foo( B() );
return 0;
}
The program output is
Hello A!
A more simpler way to define a functional object is to use lambda expressions.

Non-pointer typedef of member functions not allowed?

After getting an answer to this question I discovered there are two valid ways to typedef a function pointer.
typedef void (Function) ();
typedef void (*PFunction) ();
void foo () {}
Function * p = foo;
PFunction q = foo;
I now prefer Function * p to PFunction q but apparently this doesn't work for pointer-to-member functions. Consider this contrived example.
#include <iostream>
struct Base {
typedef void (Base :: *Callback) ();
//^^^ remove this '*' and put it below (i.e. *cb)
Callback cb;
void go () {
(this->*cb) ();
}
virtual void x () = 0;
Base () {
cb = &Base::x;
}
};
struct D1 : public Base {
void x () {
std :: cout << "D1\n";
}
};
struct D2 : public Base {
void x () {
std :: cout << "D2\n";
}
};
int main () {
D1 d1;
D2 d2;
d1 .go ();
d2 .go ();
}
But if I change it to the new preferred style: typedef void (Base :: Callback) () and Callback * cb, I get a compiler error at the point of typedef
extra qualification 'Base::' on member 'Callback'
Demo for error.
Why is this not allowed? Is it simply an oversight or would it cause problems?
For non-member functions, a type such as typedef void(Function)() has several uses, but for member functions the only application is to declare a variable which holds a function pointer. Hence, other than a stylistic preference, there's no strict need to allow this syntax and it has been omitted from the standard.
Background
The :: is a scope resolution operator, and the syntax X::Y is reserved for static member access if X is a class type. So X::*Z was another syntax invented to define pointer-to-member.
Forget member-function for a while, just think about member-data, and see this code:
struct X
{
int a;
};
int X::*pa = &X::a; //pointer-to-member
X x = {100}; //a = 100
cout << (x.*pa) << endl;
It defines a pointer-to-member-data, and the cout uses it to print the value of a of object x, and it prints:
100
Demo : http://www.ideone.com/De2H1
Now think, if X::pa (as opposed to X::*pa) were allowed to do that, then you've written the above as:
int X::pa = X::a; //not &X::a
Seeing this syntax, how would you tell if X::a is a static member or non-static member? That is one reason why the Standard came up with pointer-to-member syntax, and uniformly applies it to non-static member-data as well as non-static member-function.
In fact, you cannot write X::a, you've to write &X::a. The syntax X::a would result in compilation error (see this).
Now extend this argument of member-data to member-function. Suppose you've a typedef defined as:
typedef void fun();
then what do you think the following code does?
struct X
{
fun a;
};
Well, it defines member a of type fun (which is function taking no argument, and returning void), and is equivalent to this:
struct X
{
void a();
};
Surprised? Read on.
struct X
{
fun a; //equivalent to this: void a();
};
void X::a() //yes, you can do this!
{
cout << "haha" << endl;
}
We can use exactly the same syntax to refer to a which is now a member-function:
X x;
x.a(); //normal function call
void (X::*pa)() = &X::a; //pointer-to-member
(x.*pa)(); //using pointer-to-member
The similarity is the synatax on the right hand side : &X::a. Whether a refers to a member-function or member-data, the syntax is same.
Demo : http://www.ideone.com/Y80Mf
Conclusion:
As we know that we cannot write X::a on the RHS, no matter if a is a member-data or member-function. The only syntax which is allowed is &X::f which makes it necessary that the target type (on LHS) must be pointer as well, which in turn makes the syntax void (X::*pa)() absolutely necessary and fundamental, as it fits in with other syntax in the language.
To be precise the two typedef's in the case of the non-member pointers are not the same:
typedef void function();
typedef void (*fptr)();
The first defines function as a function taking no arguments and returning void, while the second defines ftpr as a pointer to function taking no arguments and returning void. The confusion probably arises as the function type will be implicitly converted to a pointer type in many contexts. But not all:
function f; // declares void f();
struct test {
function f; // declares void test::f()
};
void g( function f ); // declares g( void (*f)() ): function decays to pointer to function in declaration
g( f ); // calls g( &f ): function decays to pointer to function
void f() {} // definition of f
// function h = f; // error: cannot assign functions
function *h = f; // f decays to &f
Let's skip the "function" part for a second. In C++, we have the int, the int* and the int Foo::* types. That's a regular integer, pointer to integer, and a pointer to an integer member. There is no fourth type "integer member".
Exactly the same applies to functions: there's just no type "member function", even though there are function types, function pointer types, and member function pointer types.

How do function pointers work?

I'm asking some specific questions.
How can I initialize them in a class?
How can I pass a function as an argument?
Do function pointers need to be declared and defined in the class?
For question number 2 here is what I mean:
void s(void) {
//...
}
void f(function) { // what should I put as type to pass a function as an argument
//...
}
f(s);
To define a function pointer, use the following syntax:
return_type (*ref_name) (type args, ...)
So, to define a function reference named "doSomething", which returns an int and takes in an int argument, you'd write this:
int (*doSomething)(int number);
You can then assign the reference to an actual function like this:
int someFunction(int argument) {
printf("%i", argument);
}
doSomething = &someFunction;
Once that's done, you can then invoke it directly:
doSomething(5); //prints 5
Because function pointers are essentially just pointers, you can indeed use them as instance variables in your classes.
When accepting function pointers as arguments, I prefer to use a typedef instead of using the cluttered syntax in the function prototype:
typedef int (*FunctionAcceptingAndReturningInt)(int argument);
You can then use this newly defined type as the type of the argument for the function:
void invokeFunction(int func_argument, FunctionAcceptingAndReturningInt func) {
int result = func(func_argument);
printf("%i", result);
}
int timesFive(int arg) {
return arg * 5;
}
invokeFunction(10, &timesFive); //prints 50
it is not the strict answer , but to include configurable/assignable code as a class member, I would mention using a class/struct with the operator() . For example:
struct mycode
{
int k;
mycode(int k_) : k(k_)
{
}
int operator()(int x)
{
return x*k;
}
};
class Foo
{
public : Foo(int k) : f(k) {}
public : mycode f;
};
You can do:
Foo code(5);
std::cout << code.f(2) << std::endl;
it will print '10' , it I wrote everything ok.
You have to declare f in this way:
void f(void (*x)())
{
x(); // call the function that you pass as parameter (Ex. s()).
}
here is an excellent tutorial about function pointers and callbacks.
To answer 3rd question, you do not have to declare it in a class. But not to transgress encapsulation, I usually prefer member function pointers or functors which pointees are again members of classes. Examples above are C style function pointers except Luis G. Costantini R. You can take a look at this for member function pointers approach. C style function pointers are generally considered, for example, callback mechanisms where there is a C code which you receive asynchronous messages. In such cases, there are no options rather than declaring handler methods in global scope.