Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference to Function syntax - with and without &

Tags:

c++

What's the difference between

typedef void (&FunctionTypeR)();

vs

typedef void (FunctionType)();

Is the second also a reference to function? Is FunctionTypeR equivalent to FunctionType& when used as the type of an argument?

For

void foo(FunctionType bar)

Does the runtime makes a copy of the argument bar (a function) when foo is invoked?

like image 480
Candy Chiu Avatar asked Sep 06 '11 15:09

Candy Chiu


1 Answers

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

like image 70
Nawaz Avatar answered Sep 23 '22 07:09

Nawaz