Can someone please explain the Base*(*)() for me as in:
typedef std::map<std::string, Base*(*)()> map_type;
And how would one return it from a function?
I presume it is a function pointer, a Base* is returned, but what is this (*).
I found this in the following SO post Is there a way to instantiate objects from a string holding their class name?
Thanks
Base* (*)() is a type: pointer to function returning Base*. The * means that it is a pointer and the () are used to to override the precedence to ensure that the pointer applies to the function itself and not the return type.
You can return it from a function by returning the name of a function of the appropriate type.
E.g.
Base* f();
Base* (*g())()
{
return f;
}
It's the type of a function pointer of a function of signature Base*():
Base * foo();
Base * (*fp)() = &foo;
Or in your case:
map_type callbacks;
callbacks["Foo"] = &foo;
To invoke:
Base * p = callbacks["Foo"](); // same as "p = foo();"
Related
In C/C++, we can declare/define a type of pointer to function, and then declare/define some variables of this type.
But I think it is ambiguity.
For example:
typedef void ( *pFunc )();
// typedef void ( aFunc )();
void theFunc() {
cout << "theFunc has been called successfully." << endl;
};
int main() {
pFunc pf0 = theFunc;
pFunc pf1 = &theFunc;
pf0();
( *pf0 )();
pf1();
( *pf1 )();
};
Theoretically, only pFunc pf1 = &theFunc; and (*pf1)(); are legal, but all of above can pass through compilation.
In Pascal syntax, we need to define vars of function or vars of pointer to a function respectively, and the meaning of them are different and much clearer(at least I think so)!
Moreover, we can't declare/define a var of function instead of a var of pointer to function!
I tried follows and get failed.
typedef void ( aFunc )();
aFunc af0 = theFunc;
If with other types such as int/double, there are very strict syntax that restricts us to use them correctly. (If int* is not same as int, why is *pf0 is same as pf0?!)
So, Can I think it is a bug of C/C++ standard?
Some declared types:
// decltype of theFunc is void ()
// decltype of &theFunc is void (*) ()
// decltype of *theFunc is void (&) ()
Now, concerning your code, since a function is implicitly convertible to a pointer to that function, we have:
using pFunc = void(*)();
using rFunc = void(&)();
pFunc p_fct = &theFunc; // no conversion
pFunc p_fct = theFunc; // conversion lvalue to pointer
pFunc p_fct = *theFunc; // conversion lvalue reference to pointer
rFunc r_fct = *theFunc; // no conversion
rFunc r_fct = theFunc; // conversion lvalue to lvalue reference
rFunc r_fct = &theFunc; // ERROR: conversion pointer to lvalue reference not allowed
So far the conversions. Now, any object of type pFunc or rFunc is a callable object. Also, note that both (*p_fct) and (*r_fct) are of type rFunc. Therefore, you can call your function as described in the question:
p_fct(); // callable object of type pFunc
r_fct(); // callable object of type rFunc
(*p_fct)(); // callable object of type rFunc
(*r_fct)(); // callable object of type rFunc
Note that the following is equivalent to the above:
using Func = void ();
Func* p_fct = &theFunc; // no conversion
Func& r_fct = *theFunc; // no conversion
p_fct(); // callable of type Func* or pFunc
r_fct(); // callablel of type Func& or rFunc
EDIT To answer to the question: "why them was arranged in this way" from the below comment: functions cannot be copied (as explained in #JohnBurger's answer). This is why your code:
typedef void ( aFunc )();
aFunc af0 = theFunc;
doesn't work. As explained above, you can do the following though:
typedef void ( aFunc )();
aFunc* af0 = &theFunc; // or theFunc, or even *theFunc
Or you could do this:
auto myFct = theFunc;
But keep in mind that the decltype of myFct is still void (*)().
Ignore functions for a second: think about a struct.
You can have a struct, or a pointer to a struct:
typedef struct {
int x;
int y;
} Point;
Point origin = { 0, 0 };
Point here = { 1, 1 };
Point there = { 2, 2 };
int main() {
Point centre = origin;
Point *myPoint = &origin;
centre = here;
myPoint = &here;
centre = there;
myPoint = &there;
} // main()
There are three global Points: origin, here and there.
main() has two variables: centre and myPoint.
centre copies the value of origin, here, and there.
myPoint points to origin, here, and there - it does not copy them.
There is a large difference between these two ideas: one copies the whole object, while the other only points to the other object.
Now think about functions. Functions are defined by the compiler in code, and can never be copied. So it makes no sense to have function variables - how large would they be? The only sensible idea is a pointer-to-function - so that is all that the C language provides.
If you want to define a C function typedef, use the following syntax:
// Fn is a function that accepts a char and returns an int
int Fn(char c);
// FnType is the type of a function that accepts a char and returns an int
typedef int FnType(char c);
// Here is the definition of Fn
int Fn(char c) {
return c + 1;
} // Fn(c)
// Now here is how you can use FnType
int main() {
FnType *fn = &Fn;
return fn('A');
} // main()
I think that I have found the answer.
Indeed c++ standard has offered a method to declare a type of function without the help of pointers.
example:
#include <functional>
using AFunc_t = function<void( int )>;
void theFunc( int );
AFunc_t afunc = theFunc;
I hope this could help someone.
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.
typedef void (*callable_function)(double);
void call_function(callable_function func)
{
func(3.0);
}
class Foo;
union converter {
callable_function func;
void (Foo::*foo_func)(void);
};
class Foo {
private:
double d;
public:
Foo(void) : d(0.0)
{
converter c;
c.foo_func = &Foo::set_double;
call_function(c.func);//I know i can call the function directly, but that is not what i want to achieve
}
void set_double(double value)
{
d = value;
}
};
void main(void)
{
Foo foo;
}
When trying to execute the code above, i get a heap corruption error in the line:
d = value;.
Probably because the function being called is the class function, not the member function.
But if i try to change this line: c.foo_func = &Foo::set_double; to c.foo_func = &this->set_double;, i get this compiler error:
error C2276: '&' : illegal operation on bound member function expression
Question #1: Is there any way to convert the pointer(casting maybe) from void(Foo::*)(void) to void()(void) or to fix the compiler error?
pointer to "free" function and pointer to member function in C++ have different sizes.
That means you technically can cast pointer to free function to void* ptr as usually they have the same size but you cannot cast member function pointer to void* or other free function - you will get what you've got.
Check this: Pointers to members representations
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 can I convert any object of my own class convert into pointer to void?
MyClass obj;
(void*)obj; // Fail
MyClass obj;
void *p;
p = (void*)&obj; // Explicit cast.
// or:
p = &obj; // Implicit cast, as every pointer is compatible with void *
But beware ! obj is allocated on the stack this way, as soon as you leave the function the pointer becomes invalid.
Edit: Updated to show that in this case an explicit cast is not necessary since every pointer is compatible with a void pointer.
You cant convert a non-pointer to void*. You need to convert the pointer to your object to void*
(void*)(&obj); //no need to cast explicitly.
that conversion is implicit
void* p = &obj; //OK
If you use the address, you can convert it to a void pointer.
MyClass obj;
void *ptr = (void*)&obj; // Success!
To do something which has any chance of being meaningful, first you have to take the address of an object, obtaining a pointer value; then cast the pointer.
MyClass obj;
MyClass * pObj = &obj;
void * pVoidObj = (void*)pObj;
i beleive you could only convert a pointer to an object to a pointer to void ???
Perhaps: (void*)(&obj)
In addition to the technical answers: Assert, that you avoid multiple inheritance or else you don't assign the address of super-class interfaces to a void*, for they will not be unique! E.g.
class S1 { int u; };
class S2 { int v; };
class MyClass : public S1, public S2 {};
MyClass obj;
S2* s2 = &obj;
void * p1 = &obj;
void * p2 = s2;
Here p1 and p2 (==s2) will be different, because the S2 instance in C has an address offset.