What is `R(*pf)(void*, Args...)`, function pointer to a method? - c++

I saw this type here. I believe he's trying to create a variable pf for a member pointer type-erased (that's why there's void* there). I then noticed this type signature in similar such classes.
But according to isocpp a non-static member pointer type is defined like this:
int (Fred::*)(char,float) (for some class Fred)
and a function pointer type is defined like this:
int (*)(char,float)
Therefore one would create a member pointer variable mp like this:
int (S::*mp)(int) = nullptr;
Maybe this void* represents this* and its another way to define a member pointer variable by defining a function pointer variable? Is this possible?
What is R(*pf)(void*, Args...)?

It's the declaration of a function pointer. Nothing more than that.
Compatible functions take void* and Args..., and return R.
In the given example, the compatible function that's assigned to the pointer, is a lambda. The void* is the type-erased address of some callable f, and the Args... members are, well, the arguments that'll be passed to that callable. The callable's type is restored by capturing of type aliases inside the lambda (nice!).

R(*pf)(void*, Args...) is a function pointer (regular one, not pointer-to-member) to a function that returns R and has (void*, Args...) parameters, where Args... is a list of types (an expanded template parameter pack).
Maybe this void* represents this* and its another way to define a member pointer variable
Nah, there is no such feature in C++.
If you look at the code, the only things assigned to this pointer are lambdas, like this one:
pf = [](void* ptr, Args... args)->R{
return blah;
};
I'm not sure why you expected pointers-to-members to be involved.

Related

Why cpp std::function can hold capture-lambda, while function pointer cannot?

I've got this code snippet:
int x = 3;
auto fauto = [=](){ cout<<'x'; };
function<void()> func{fauto};
func();
void (*rawPf)() = fauto; // fail to compile
rawPf();
I knew the syntax that only non-capture lambda can be assigned to function pointer. But:
(1) Why std::function can hold capture-lambda?
(2) as both std::function and function pointers are callable, what's the core difference that makes std::function able to hold capture-lambda, while function pointer cannot?
Any detailed explanation on language design for this?
Why can a function pointer not hold a lambda with a capture : because a Lambda is NOT a function ,it's an object!
Why can a lambda without a capture be converted to a function pointer ?
A Lambda is just an ordinairy object (a piece of data) of a compiler generated class (with a unique classname that only the compiler knows) with a function-operator member (i.e. auto operator() ( ??? )) that the compiler defines for you with the parameter definitions (if any) you provide. The data-members of a lambda-object are defined by the capture-list and/or usage of variables of its enclosing scope.
All non-static member functions when called on an object get a implicit hidden argument called this. This is also the case when you 'call' the lambda.
Now ,when you don't capture something ,the lambda has no data (empty class) and the compiler doesn't have to generate an implicit this pointer for the call ,which makes the function operator just like an ordinairy function and the compiler can convert it to function pointer.
So it not the lambda that is converted to a function-pointer ,it's the lambda's function-operator that is converted.
Why can std::function hold both : because it's a template and with templates and specializations you can do almost anything.
There's no reason not to implement it in std::function<>, so it's implemented.
The reason a function pointer cannot hold a capture lambda is that the latter has a this pointer and there's no place to store that in the function pointer (well, unless you compile new code or assign it from a pool). However, std::function<> can allocate arbitrary amount of space, amongst these, the this pointer.
You can understand this better if you try to implement a function returning function pointers for lambdas (which, when called, by specification should call the lambda).

What does T::* signify in the declaration of a function parameter list?

I declare a particular keyboard callback function as this inside my code:
void keyboardEventCallback(const pcl::visualization::KeyboardEvent &event, void* viewer_void, void* widget_void);
The keyboard event is the actual event passed to the callback function, the viewer_void parameter is a pointer to a PCLVisualizer class that generates a window for rendering, and widget_void is a pointer to a widget that interfaces with Qt.
In the documentation for pcl, a registration function passes the arguments for registering the keyboard function like
boost::signals2::connection registerKeyboardCallback(void(T::*callback)(const pcl::visualization::KeyboardEvent&, void*), T& instance, void* cookie=nullptr)
So my question is, what is the meaning of T::* inside the registration function declaration, and why am I not allowed to pass this:
m_vis->registerKeyboardCallback(keyboardEventCallback, (void*)&m_vis, (void*)this);
where m_vis is a visualizer, keyboardcallback is the callback, and this is the widget.
Why can I not register like this. This is for the point cloud library.
what is the meaning of T::* inside the registration function declaration
This is the syntax of a pointer to member. Let's take a look at the whole type and name of the parameter:
void(T::*callback)(const pcl::visualization::KeyboardEvent&, void*)
This is the declaration of a variable named callback. It's a pointer to member function. More precisely, it's a pointer to member function of the class T.
If we take the name out of the type, we see things more clearly:
// class name ---v v------- parameters
void(T::*)(const pcl::visualization::KeyboardEvent&, void*)
// ^---- return type
It's in fact, a pointer to function member of the class T that returns void. It's a function that takes strictly two parameters: a const pcl::visualization::KeyboardEvent& and a void*.
why am I not allowed to pass this
It's simple. Look at the type of your function:
using func_type = decltype(keyboardEventCallback);
// hint: the type is: void(*)(const pcl::visualization::KeyboardEvent&, void*, void*)
Let's compare the two types side by side:
void(*)(const pcl::visualization::KeyboardEvent&, void*, void*)
void(T::*)(const pcl::visualization::KeyboardEvent&, void*)
First, your function is not a member function, it's a plain function pointer. It's not the same type. Then, you got three arguments, as the type of the parameter only ask for two. This is different.
Now, how can you fix this??
You could use a lambda:
auto myCallback = [](const pcl::visualization::KeyboardEvent& e, void* c) { /* ... */ }
using lambdaType = decltype(myCallback);
// Be careful here, we don't want our lambda to go out of scope when it is called.
m_vis->registerKeyboardCallback(&lambdaType::operator(), myCallback, this);
Or even simpler: just define keyboardEventCallback inside your class, and send it:
// don't forget: keyboardEventCallback must receive the same parameter as asked.
m_vis->registerKeyboardCallback(&MyClass::keyboardEventCallback, *this, this);
This is the syntax for member functions.
Example:
class A{
int giveMe5();
};
&A::giveMe5; // will be of type int(A::*)()
Why does the type differ from free functions and static member functions ?
Because member functions have an implicit parameter that points to the object on which the function gets called.
https://isocpp.org/wiki/faq/pointers-to-members#fnptr-vs-memfnptr-types
says:
The type of this function is different depending on whether it is an ordinary function or a non-static member function of some class:
- Its type is int (*)(char,float) if an ordinary function
- Its type is int (Fred::*)(char,float) if a non-static member function of class Fred

How std::bind works with member functions

I'm working with std::bind but I still don't get how it works when we use it with member class functions.
If we have the following function:
double my_divide (double x, double y) {return x/y;}
I understand perfectly well the next lines of code:
auto fn_half = std::bind (my_divide,_1,2); // returns x/2
std::cout << fn_half(10) << '\n'; // 5
But now, with the following code where we have a bind to member function I have some questions.
struct Foo {
void print_sum(int n1, int n2)
{
std::cout << n1+n2 << '\n';
}
int data = 10;
};
Foo foo;
auto f = std::bind(&Foo::print_sum, &foo, 95, _1);
f(5);
Why is the first argument a reference? I'd like to get a theoretical explanation.
The second argument is a reference to the object and it's for me the most complicated part to understand. I think it's because std::bind needs a context, am I right? Is always like this? Has std::bind some sort of implementation to require a reference when the first argument is a member function?
When you say "the first argument is a reference" you surely meant to say "the first argument is a pointer": the & operator takes the address of an object, yielding a pointer.
Before answering this question, let's briefly step back and look at your first use of std::bind() when you use
std::bind(my_divide, 2, 2)
you provide a function. When a function is passed anywhere it decays into a pointer. The above expression is equivalent to this one, explicitly taking the address
std::bind(&my_divide, 2, 2)
The first argument to std::bind() is an object identifying how to call a function. In the above case it is a pointer to function with type double(*)(double, double). Any other callable object with a suitable function call operator would do, too.
Since member functions are quite common, std::bind() provides support for dealing with pointer to member functions. When you use &print_sum you just get a pointer to a member function, i.e., an entity of type void (Foo::*)(int, int). While function names implicitly decay to pointers to functions, i.e., the & can be omitted, the same is not true for member functions (or data members, for that matter): to get a pointer to a member function it is necessary to use the &.
Note that a pointer to member is specific to a class but it can be used with any object that class. That is, it is independent of any particular object. C++ doesn't have a direct way to get a member function directly bound to an object (I think in C# you can obtain functions directly bound to an object by using an object with an applied member name; however, it is 10+ years since I last programmed a bit of C#).
Internally, std::bind() detects that a pointer to a member function is passed and most likely turns it into a callable objects, e.g., by use std::mem_fn() with its first argument. Since a non-static member function needs an object, the first argument to the resolution callable object is either a reference or a [smart] pointer to an object of the appropriate class.
To use a pointer to member function an object is needed. When using a pointer to member with std::bind() the second argument to std::bind() correspondingly needs to specify when the object is coming from. In your example
std::bind(&Foo::print_sum, &foo, 95, _1)
the resulting callable object uses &foo, i.e., a pointer to foo (of type Foo*) as the object. std::bind() is smart enough to use anything which looks like a pointer, anything convertible to a reference of the appropriate type (like std::reference_wrapper<Foo>), or a [copy] of an object as the object when the first argument is a pointer to member.
I suspect, you have never seen a pointer to member - otherwise it would be quite clear. Here is a simple example:
#include <iostream>
struct Foo {
int value;
void f() { std::cout << "f(" << this->value << ")\n"; }
void g() { std::cout << "g(" << this->value << ")\n"; }
};
void apply(Foo* foo1, Foo* foo2, void (Foo::*fun)()) {
(foo1->*fun)(); // call fun on the object foo1
(foo2->*fun)(); // call fun on the object foo2
}
int main() {
Foo foo1{1};
Foo foo2{2};
apply(&foo1, &foo2, &Foo::f);
apply(&foo1, &foo2, &Foo::g);
}
The function apply() simply gets two pointers to Foo objects and a pointer to a member function. It calls the member function pointed to with each of the objects. This funny ->* operator is applying a pointer to a member to a pointer to an object. There is also a .* operator which applies a pointer to a member to an object (or, as they behave just like objects, a reference to an object). Since a pointer to a member function needs an object, it is necessary to use this operator which asks for an object. Internally, std::bind() arranges the same to happen.
When apply() is called with the two pointers and &Foo::f it behaves exactly the same as if the member f() would be called on the respective objects. Likewise when calling apply() with the two pointers and &Foo::g it behaves exactly the same as if the member g() would be called on the respective objects (the semantic behavior is the same but the compiler is likely to have a much harder time inlining functions and typically fails doing so when pointers to members are involved).
From std::bind docs:
bind( F&& f, Args&&... args ); where f is a Callable, in your case that is a pointer to member function. This kind of pointers has some special syntax compared to pointers to usual functions:
typedef void (Foo::*FooMemberPtr)(int, int);
// obtain the pointer to a member function
FooMemberPtr a = &Foo::print_sum; //instead of just a = my_divide
// use it
(foo.*a)(1, 2) //instead of a(1, 2)
std::bind(and std::invoke in general) covers all these cases in a uniform way. If f is a pointer-to-member of Foo, then the first Arg provided to bind is expected to be an instance of Foo (bind(&Foo::print_sum, foo, ...) also works, but foo is copied) or a pointer to Foo, like in example you had.
Here is some more reading about pointers to members, and 1 and 2 gives full information about what bind expects and how it invokes stored function.
You also can use lambdas instead std::bind, which could be more clear:
auto f = [&](int n) { return foo.print_sum(95, n); }

using typedef to wrap functions

One of my teachers use this type declaration:
typedef void (*SortFunction)(int a[], int n);
to create a type that can hold a pointer to a function
and that can be used to call that function later on in a program.
I also know that to pass a function as a parameter you have to
wrap the function name in parenthesis and wrap the function's
parameters in parenthesis after the function name as well like so
function someFunction( (anotherfunction)(type arg1, type arg2,...)){
...
}
What I want to know is why must you wrap a function in parenthesis like this? is this a built in function of most c++ compilers or is it simply a trick that we programmers use
in order to enable functions as arguments within our code? also, why does "SortFunction"
in the typedef statement need to be referenced, why can't the variable you use to utilize SortFunction just hold the function instead of pointing to it?
There's nothing special about function arguments. Whenever you declare a function pointer (as a local variable, global variable, class member variable, function parameter, typedef, etc.), it's always declared like so:
return_type (*var_name)(T1 param1, T2 param2, /* etc. */ );
// ^
// |
// This * is very important!
Where var_name is the name of the function pointer variable. The reason the parentheses are needed around *var_name is due to operator precedence: without the parentheses, the * (indicating that something's a pointer) would match with the function's return type, and instead you'd get something like a return type of int* (pointer to int) instead of plain int.
You can't pass a function as an argument because functions are not first-class objects in C and C++. The only way to pass a function is my passing a pointer to the function.
"I also know that to pass a function as a parameter you have to wrap the function name in parenthesis..." You "know " incorrectly.
In order to pass function pointer as a parameter you don't have to wrap the name in parentheses. For example, this will work perfectly fine
void foo(int i) {
}
void bar(void f(int)) {
f(5);
}
int main() {
bar();
}
In the above example function bar receives a pointer to function foo as a parameter and calls foo through that pointer, passing 5 as an argument. As you can see, function name f in the parameter declaration is not wrapped into parentheses.
In this case, once again, the type of parameter f is actually a pointer to a function, even though it is not explicitly declared as a pointer. When function type is used in function parameter declarations, it is automatically implicitly "replaced" with function pointer type by the compiler.
If you wanted to use the function pointer type explicitly, you have to declare bar as
void bar(void (*f)(int)) {
f(5);
}
In this case the parentheses in (*f) are necessary to assure that the * will get bound to f and not to void. Without parentheses the void *f(int) declaration would stand for "function returning void *" instead of the desired "pointer to function returning void".
It is a matter of syntax. Your first typedef defines a type which is a function receiving a vector of int and a int and returning nothing (void).
A variable of type SortFunction will be conceptually as any other variable, although it points to some function. The advantage is that you can change the function it points to and/or call the function dynamically.
What I want to know is why must you wrap a function in parenthesis like this?
Because there had to be some way to identify a function pointer to the compiler (or rather, the parser) and that way seemed as good as any. In C++11 land, you might use this instead: std::function<void(std::array<int>&)> instead.
is this a built in function of most c++ compilers or is it simply a trick that we programmers use in order to enable functions as arguments within our code?
Function pointers need a little bit of additional magic, and without compiler support they would be very, very inconvenient to use. I'm also reasonably certain that it is in the nature of programming that almost all programmer tricks are ultimately functions of the compiler!
also, why does "SortFunction" in the typedef statement need to be referenced, why can't the variable you use to utilize SortFunction just hold the function instead of pointing to it?
Hmm. Not totally sure what you mean here. Do you mean "why does this need to be a typedef at all... why couldn't I just write out the whole function pointer prototype in my function arguments"? Cos you can:
void foo(void(*funcptr)()) {}
If you meant "why do function pointers have to point at a function instead of having the code inline" then for that you need C++11 and lambdas:
#include <iostream>
#include <functional>
void foo(std::function<void(void)> bar) { bar(); }
int main(int argc, char* argv[])
{
foo([]() { std::cout << "hi!" << std::endl; });
}
(again, special syntax needed for lambdas, [](){}, just to tell the parser what is going on)

Syntax of C++ templates with function type parameters

I'm used to seeing syntax like this for function pointers
int (*pointer_name) (float, char *);
void call_function (void (*)(int), int);
In some C++03 functional libraries I see types used this way:
abc::function<void(*)(int,float)> f;
In C++11's std::function I see the type given this way
std::function<void(int,float)> f;
There is a missing (*). Why?
The C++03 function<T> has T being an identical type to the corresponding function pointer. It's easy to imagine the implementation.
std::function in C++11 is supported by core language enhancements. Have template argument types been extended to accomodate callability?
std::function (and its inspiration, boost::function) does not only store function pointers. It can also store function objects. In that sense, passing a function signature as a template parameter is similar to how a smart pointer usually take the type of the pointee as a template parameter, not a pointer type!
Contrast:
int* p; // indirection to an object of type int
std::unique_ptr<int> q; // indirection to an object of type int
with
typedef void signature_type(); // a function type
// indirection to something callable with signature_type as a signature
// i.e. f() has type void
// only work for freestanding functions however
signature_type* f;
// indirection to something callable with signature_type as a signature
// i.e. g() has type void
// not restricted to function pointers!
std::function<signature_type> g;
This is a useful convention.
There is nothing magic here, the type
void(int,float)
is the type of a function without the names. It matches a function like void g(int x, float y).
With templates you don't have to use function pointers, you can use function types as well.
As with other elements, functions have a type, and you can use either the type or the pointer to the type in different contexts. The missing (*) you are expecting is just the pointer-to syntax.
int (*pointer_name) (float, char *);
typedef int my_function_type(float,char*);
my_function_type * pointer_name2;
The types of pointer_name and pointer_name2 are the same: pointer to a function that returns int and takes two arguments of types float and char*. Note that this is exactly equivalent to other types like int, with the difference that you cannot declare a variable to be of type function, only pointer to function.
The interface of std::function (or boost::function) just takes the signature of the function. The type argument is not a pointer to function but rather the type of a function (like my_function_type in the code above)
Function types aren't new in C++11 (see 8.3.5 in C++98). IIRC, the improvement over what TR1 and boost provide for function are quite minor.