The difference is that you cannot create objects of function type, but you can create of objects of function pointer type, and function reference type.
That means if you've a function, say f()
as:
void f(){}
then here is what you can do, and what you cannot do:
FunctionType fun1 = f; //error - cannot create object of function type
FunctionType *fun2 = f; //ok
FunctionTypeR fun3 = f; //ok
Test code:
typedef void (&FunctionTypeR)();
typedef void FunctionType();
void f(){}
int main() {
FunctionType fun1 = f; //error - cannot create object of function type
FunctionType *fun2 = f; //ok
FunctionTypeR fun3 = f; //ok
return 0;
}
Now see the compilation error (and warnings):
prog.cpp: In function ‘int main()’:
prog.cpp:7: error: function ‘void fun1()’ is initialized like a variable
prog.cpp:8: warning: unused variable ‘fun2’
prog.cpp:9: warning: unused variable ‘fun3’
Online demo : http://ideone.com/hpTEv
However, if you use FunctionType
(which is a function type) in a function parameter list as:
void foo(FunctionType bar);
then it's equivalent to
void foo(FunctionType * bar);
That means, no matter what you write, you can call the function using bar
as:
bar(); //ok
(*bar)(); //ok
That is, you can write this:
void h(FunctionType fun) { fun(); }
void g(FunctionType fun) { (*fun)(); }
Demo : http://ideone.com/kwUE9
This is due to function type to function pointer type adjustment; that is, the function type is adjusted to become a pointer to function type:
Function type | Function pointer type (adjusted type)
void () | void (*)()
void (int) | void (*)(int)
int (int,int) | int (*)(int,int)
.... | ... so on
The C++03 Standard says in §13.1/3,
Parameter declarations that differ only in that one is a function type and the other is a pointer to the same function type are equivalent. That is, the function type is adjusted to become a pointer to function type (8.3.5).
[Example:
void h(int());
void h(int (*)()); // redeclaration of h(int())
void h(int x()) { } // definition of h(int())
void h(int (*x)()) { } // ill-formed: redefinition of h(int())
]
And if you use `FunctionTypeR
(which is a function reference type) as:
void foo(FunctionTypeR bar);
then it's equivalent to:
void foo(FunctionType * & bar);
And,
void h(FunctionTypeR fun) { fun(); }
void g(FunctionTypeR fun) { (*fun)(); }
Demo : http://ideone.com/SmtQv
Interesting part...
You can use FunctionType to declare a function (but not to define it).
For example,
struct A
{
//member function declaration.
FunctionType f; //equivalent to : void f();
};
void A::f() //definition
{
std::cout << "haha" << std::endl;
}
//forward declaration
FunctionType h; //equivalent to : void h();
int main() {
A a;
a.f(); //call member function
h(); //call non-member function
}
void h() //definition goes below main()
{
std::cout <<"hmmm.." << std::endl;
}
Demo : http://ideone.com/W4ED2