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 (*)()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With