Reference to Function syntax - with and without & - 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?

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

Related

Why is this overloaded std::function parameter ambiguous?

I have the below code, where a class is trying to take one of two std::function signatures through its constructor. I'm able to get the signature that has the double parameter to compile, but the parameter-less signature fails to compile, saying the call is ambiguous.
#include <functional>
class Foo
{
public:
void baz(double value) {
}
};
class Bar
{
public:
void baz() {
}
};
class Overloader {
public:
Overloader(std::function<void(double)> inFuncWithArg)
: funcWithArg(inFuncWithArg)
{
}
Overloader(std::function<void(void)> inFuncNoArg)
: funcNoArg(inFuncNoArg)
{
}
private:
std::function<void(double)> funcWithArg;
std::function<void(void)> funcNoArg;
};
int main()
{
Foo foo;
Bar bar;
// Compiles
Overloader overloader1(std::bind(static_cast<void(Foo::*)(double)>(&Foo::baz)
, &foo, std::placeholders::_1));
// Fails to compile - "call of overloaded ‘Overloader(std::_Bind_helper::type)’ is ambiguous"
Overloader overloader2(std::bind(static_cast<void(Bar::*)(void)>(&Bar::baz)
, &bar));
return 0;
}
What am I missing that's causing this to fail? Also, are there any less-verbose ways to do this?
Here's the full error output
main.cpp: In function ‘int main()’:
main.cpp:51:20: error: call of overloaded ‘Overloader(std::_Bind_helper::type)’ is ambiguous
, &bar));
^
main.cpp:32:5: note: candidate: Overloader::Overloader(std::function)
Overloader(std::function<void(void)> inFuncNoArg)
^~~~~~~~~~
main.cpp:27:5: note: candidate: Overloader::Overloader(std::function)
Overloader(std::function<void(double)> inFuncWithArg)
^~~~~~~~~~
This question is more about std::bind than std::function.
The result of the expression
std::bind(&Foo::baz, &foo, std::placeholders::_1)
is invocable with one or more arguments, where the first argument is convertible to double.
The result of the expression
std::bind(&Bar::baz, &bar)
is invocable with zero or more arguments, with no restrictions.
The first expression can thus only initialize std::function<void(double)>, but the second expression can initialize either std::function<void(double)> or std::function<void(void)> and is ambiguous.
Genuinely, do not use std::bind. You can use std::bind_front if you have it. Alternatively, use a lambda.
std::bind_front:
std::bind_front(&Foo::baz, &foo)
std::bind_front(&Bar::baz, &bar)
lambda:
[&foo](double) { foo.baz(value); }
[&bar] { bar.baz(); }
Just use a lambda:
auto overloader1 = [&foo](double value) { foo.baz(value); };
auto overloader2 = [&bar]() { bar.baz(); }

Template pass member function with args and return value as parameter c++

I would like to pass a templated function args for class and a method of that class to call. The method has arguments as well as a return value.
Here is what I have so far. I believe I'm getting a little tripped up on the templatized function syntax:
bar.h
class Bar {
public:
Bar();
int FuncBar(int arg1);
}
foo.h
template<typename A, int (A::*Method)()>
int FuncTemplate(A* a, int bar_arg1) {
....
return a->Method(bar_arg1)
}
class Foo {
public:
explicit Foo(Bar* bar);
private:
void FuncFoo();
Bar* bar_;
}
foo.cc
Foo::Foo(Bar bar) : bar_(bar) {};
void Foo::FuncFoo() {
...
int bar_arg1 = 0;
FuncTemplate<Bar, &(*bar_)::FuncBar>(bar_, bar_arg1);
}
You need to use int (A::*Method)(int) as the function pointer type since the member function expects an int as an argument.
Also, the call to the member function needs to be (a->*Method)(bar_arg1). The syntax for calling member function using a member function is not very intuitive.
template<typename A, int (A::*Method)(int)>
int FuncTemplate(A* a, int bar_arg1) {
....
return (a->*Method)(bar_arg1)
}
Also, you need to use &Bar::FuncBar to get a pointer to the member function, not &(*bar_)::FuncBar.
void Foo::FuncFoo() {
int bar_arg1 = 0;
FuncTemplate<Bar, &Bar::FuncBar>(bar_, bar_arg1);
// ^^^^^^^^^^^^^
}

Why does taking a member function pointer value requires class name qualification even from inside of the class?

When returning a member function pointer to a class within one of that class's member functions I still have to specify the class. I cannot simply take the address. For example, this code works fine:
class Foo {
public:
void func(int param) { cout << param << endl; }
void (Foo::*getPointer())(int) { return &Foo::func; }
};
But if in getPointer I try to simply do: return &func I get this error:
prog.cpp: In member function 'void (Foo::* Foo::getPointer())(int)':
prog.cpp:8:43: error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say '&Foo::func' [-fpermissive]
void (Foo::*getPointer())(int) { return &func; }
Why must I specify the class when that's the context that I am within?
Pointers and pointer to members are distinct types, we can see that from section the draft C++ standard section 3.9.2 [basic.compound] which includes a compound type for pointer as well as pointer to non-static class member and notes:
Static class members are objects or functions, and pointers to them
are ordinary pointers to objects or functions
This issue with this is I think well described in this quote in an answer from Johannes from the Annotated C++ Reference Manual(ARM):
Note that the address-of operator must be explicitly used to get a
pointer to member; there is no implicit conversion ... Had there been,
we would have an ambiguity in the context of a member function ... For
example,
void B::f() {
int B::* p = &B::i; // ok
p = B::i; // error: B::i is an int
p = &i; // error: '&i'means '&this->i'
// which is an 'int*'
int *q = &i; // ok
q = B::i; // error: 'B::i is an int
q = &B::i; // error: '&B::i' is an 'int B::*'
}
In particular these lines:
int B::* p = &B::i; // OK
and:
p = &i; // error: '&i'means '&this->i' which is an 'int*'
demonstrate the difference between the qualified and the unqualified name.
(...there was a wrong answer...)
It looks more strange in the following context:
class Foo {
public:
virtual void func(int param) { cout << param << endl; }
void call(int x) { Foo::func(x); }
void (Foo::*getPointer())(int) { return &Foo::func; }
};
class Bar : public Foo {
public:
void func(int param) override { cout << "Hello world!" << endl; }
};
int main() {
Foo *a = new Bar();
auto p = a->getPointer();
(a->*p)(4);
a->call(4);
return 0;
}
The output is
Hello world
4
Calling Foo::func is a call of func in Foo class while calling &Foo::func is a virtual call.

a strange use of typedef

I have never see a grammar in c++ like this before:
typedef int (callback)(int);
what really does this really mean?I just find that if I create a statement
callback a;
It's effect is very very similar to a forward function declaration.
below is the code I had written
#include<cstdio>
int callbackfunc(int i)
{
printf("%d\n",i);
return i*i;
}
// you can also use typedef int (callback)(int) here!
typedef int (*callback)(int);
void func(callback hook)
{
hook(hook(3));
}
int main()
{
func(callbackfunc);
getchar();
return 0;
}
You can use
typedef int (*callback)(int);//this is very common to use
in this code,but if we change it to
typedef int (callback)(int); //I'm puzzled by this !
this will also get the same result!
and I know typedef int (*callback)(int) and typedef int (callback)(int)
are two completely different stuff.
Its because of the fact that in the parameter declaration, the function-type is adjusted to become a pointer-to-function-type.
typedef int type(int);
typedef int (*type)(int);
The first typedef defines a type which is called function-type, while the second typedef defines a type which is called pointer-to-function-type. In the parameter declaration, function-type is adjusted to become a pointer to function type.
§13.1/3 (C++03) says,
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())
]
An interesting example of the exclusive usage of function-type
Suppose you've a typedef, defined as:
typedef void funtype();
then you can use this to define member-function as:
struct A
{
//member function declaration.
funtype f; //equivalent to : void f();
};
void A::f() //definition
{
std::cout << "haha" << std::endl;
}
Test code:
int main() {
A a;
a.f(); //call member function
}
Output:
haha
Online demo: http://ideone.com/hhkeK
It's because a function implicitly becomes a function pointer where necessary. These are identical:
func(callbackfunc);
func(&callbackfunc);

Non-pointer typedef of member functions not allowed?

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.