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, ×Five); //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.
Related
I was reading about std::invoke on cpp reference and was wondering in which situations we would ever need to pass as a first argument a pointer to data member and an object as second argument.
From cpp reference it states this:
Invoke the Callable object f with the parameters args. As by INVOKE(std::forward(f), std::forward(args)...).
where INVOKE(f, t1, t2, ..., tN) is defined as follows:
...
and then the second point is:
Otherwise, if N == 1 and f is a pointer to data member of class
Ok, let's look at this further and suppose I'm using std::thread (which constructor's uses std::invoke):
For example, it is a bit unclear to me when it would be useful (or what can force one) to use a threads this way ?
struct Foo {
Foo(int num) : num_(num) {}
void print_add(int i) const { std::cout << num_+i << '\n'; }
int num_;
void print_num(int i) const {
std::cout << i << '\n';
}
};
int main() {
const Foo foo(314159);
std::thread t(&Foo::num_, foo);
t.join();
return 0;
}
And how a pointer to data member can be associated with a callable concept ?
You might think that only pointers to member functions are useful. That is, something like:
struct Widget {
bool valid() const;
};
std::vector<Widget> widgets;
bool all_valid = std::ranges::all_of(widgets, &Widget::valid);
That would std::invoke the pointer to member function &Widget::valid on each of the Widgets. But you could just as easily have constructed Widget such that valid is just a flag instead of being a member function. And checking that all the Widgets are valid is just as reasonable a thing to do:
struct Widget {
bool valid;
};
std::vector<Widget> widgets;
bool all_valid = std::ranges::all_of(widgets, &Widget::valid);
The only difference is that this std::invokes a pointer to member data instead of a pointer to member function. But still useful.
#include <iostream>
template <int N>
class X {
public:
using I = int;
void f(I i) {
std::cout << "i: " << i << std::endl;
}
};
template <int N>
void fppm(void (X<N>::*p)(typename X<N>::I)) {
p(0);
}
int main() {
fppm(&X<33>::f);
return 0;
}
I just don't understand the compile error message of the code.
error: called object type 'void (X<33>::*)(typename X<33>::I)' is not a function or function pointer
p(0);
I think p is a function which returns void and takes int as its argument. But apparently, it's not. Could somebody give me clue?
Since p is a pointer to a nonstatic member function, you need an instance to call it with. Thus, first instantiate an object of X<33> in main:
int main() {
X<33> x;
fppm(x, &X<33>::f); // <-- Signature changed below to accept an instance
Then in your function, change the code to accept an instance of X<N> and call the member function for it:
template <int N>
void fppm(X<N> instance, void (X<N>::*p)(typename X<N>::I)) {
(instance.*p)(0);
}
The syntax may look ugly but the low precedence of the pointer to member operator requires the need for the parentheses.
As denoted in the comments already, p is a pointer to member function, but you call it like a static function (p(0);). You need a concrete object to call p on:
X<N> x;
(x.*p)(0);
// or:
X<N>* xx = new X<N>();
(xx->*p)(0);
delete xx;
Be aware that the .*/->* operators have lower precedence than the function call operator, thus you need the parentheses.
Side note: Above is for better illustration, modern C++ might use auto keyword and smart pointers instead, which could look like this:
auto x = std::make_unique<X<N>>();
(x.get()->*p)(0);
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.
I have the following function:
void PerformAction(void(*pf_action)());
and the following class:
class A
{
public:
void DoSomething();
}
I want to be able to do this:
int main()
{
A a;
PerformAction(&(a.DoSomething);
return 0;
}
I have seen many answers that say that the function signature should be:
void PerformAction(void(A::*)());
This is not what I want.
I want to able to pass it any function/method that receives no parameters and returns void. Not just member methods of A or just global functions.
Is this possible in C++?
Plain function pointers and member function pointers are different things.
Member functions take a hidden this parameter, whereas plain functions do not. To call a member function through a pointer an object is required to initialize that this parameter.
Hence, you cannot convert a pointer to a non-static member function to a plain function pointer and call through it without passing in an object.
I want to able to pass it any function/method that receives no parameters and returns void. Not just member methods of A or just global functions.
Is this possible in C++?
Yes, it is possible, but you need to use a more flexible type. The way to achieve this is to specify the PerformAction function with a different type. You want to use a type that is callable with zero arguments and returns void, std::function<void ()>. For example change the PerformAction function to be: void PerformAction(std::function<void ()> fn);. This version will allow you to accept anything that's callable with zero arguments and returns void, see the following code for an example.
Example Code
#include <functional>
#include <iostream>
class Foo
{
public:
void bar() { std::cout << "Member function: Foo::bar()\n"; }
};
void bar()
{
std::cout << "Free function: bar()\n";
}
class Functor
{
public:
void operator()() { std::cout << "Functor object\n"; }
};
auto lambda = []() { std::cout << "Lambda expression\n"; };
void doSomething(std::function<void ()> fn)
{
fn();
}
int main()
{
doSomething(bar);
doSomething(Functor());
doSomething(lambda);
Foo foo;
doSomething(std::bind(&Foo::bar, &foo));
return 0;
}
Live Example
Example Output
Free function: bar()
Functor object
Lambda expression
Member function: Foo::bar()
Alright, I think the title is sufficiently descriptive (yet confusing, sorry).
I'm reading this library: Timer1.
In the header file there is a public member pointer to a function as follows:
class TimerOne
{
public:
void (*isrCallback)(); // C-style ptr to `void(void)` function
};
There exists an instantiated object of the TimerOne class, called "Timer1".
Timer1 calls the function as follows:
Timer1.isrCallback();
How is this correct? I am familiar with calling functions via function pointers by using the dereference operator.
Ex:
(*myFunc)();
So I would have expected the above call via the object to be something more like:
(*Timer1.isrCallback)();
So, what are the acceptable options for calling functions via function pointers, as both stand-alone function pointers and members of an object?
See also:
[very useful!] Typedef function pointer?
Summary of the answer:
These are all valid and fine ways to call a function pointer:
myFuncPtr();
(*myFuncPtr)();
(**myFuncPtr)();
(***myFuncPtr)();
// etc.
(**********************************f)(); // also valid
Things you can do with a function pointer.
1: The first is calling the function via explicit dereference:
int myfunc(int n)
{
}
int (*myfptr)(int) = myfunc;
(*myfptr)(nValue); // call function myfunc(nValue) through myfptr.
2: The second way is via implicit dereference:
int myfunc(int n)
{
}
int (*myfptr)(int) = myfunc;
myfptr(nValue); // call function myfunc(nValue) through myfptr.
As you can see, the implicit dereference method looks just like a normal function call -- which is what you’d expect, since function are simply implicitly convertible to function pointers!!
In your code:
void foo()
{
cout << "hi" << endl;
}
class TimerOne
{
public:
void(*isrCallback)();
};
int main()
{
TimerOne Timer1;
Timer1.isrCallback = &foo; //Assigning the address
//Timer1.isrCallback = foo; //We could use this statement as well, it simply proves function are simply implicitly convertible to function pointers. Just like arrays decay to pointer.
Timer1.isrCallback(); //Implicit dereference
(*Timer1.isrCallback)(); //Explicit dereference
return 0;
}
You don't have to dereference a function pointer to call it. According to the standard ([expr.call]/1),
The postfix expression shall have
function type or pointer to function type.
So (*myFunc)() is valid, and so is myFunc(). In fact, (**myFunc)() is valid too, and you can dereference as many times as you want (can you figure out why?)
You asked:
Timer1 calls the function as follows:
Timer1.isrCallback();
How is this correct?
The type of Timer1.isrCallback is void (*)(). It is a pointer to a function. That's why you can use that syntax.
It is similar to using:
void foo()
{
}
void test_foo()
{
void (*fptr)() = foo;
fptr();
}
You can also use:
void test_foo()
{
void (*fptr)() = foo;
(*fptr)();
}
but the first form is equally valid.
Update, in response to comment by OP
Given the posted definition of the class you would use:
(*Timer1.isrCallback)();
To use
(Timer1.*isrCallback)();
isrCallback has to be defined as a non-member variable of whose type is a pointer to a member variable of TimerOne.
void (TimerOne::*isrCallback)();
Example:
#include <iostream>
class TimerOne
{
public:
void foo()
{
std::cout << "In TimerOne::foo();\n";
}
};
int main()
{
TimerOne Timer1;
void (TimerOne::*isrCallback)() = &TimerOne::foo;
(Timer1.*isrCallback)();
}
Output:
In TimerOne::foo();
(Test this code)
If you want to define isrCallbak as a member variable of TimerOne, you'll need to use:
#include <iostream>
class TimerOne
{
public:
void (TimerOne::*isrCallback)();
void foo()
{
std::cout << "In TimerOne::foo();\n";
}
};
int main()
{
TimerOne Timer1;
Timer1.isrCallback = &TimerOne::foo;
// A little complicated syntax.
(Timer1.*(Timer1.isrCallback))();
}
Output:
In TimerOne::foo();
(Test this code)