In the code below, function-pointer and what i considered as "function-reference" seems to have identical semantics:
#include <iostream>
using std::cout;
void func(int a) {
cout << "Hello" << a << '\n';
}
void func2(int a) {
cout << "Hi" << a << '\n';
}
int main() {
void (& f_ref)(int) = func;
void (* f_ptr)(int) = func;
// what i expected to be, and is, correct:
f_ref(1);
(*f_ptr)(2);
// what i expected to be, and is not, wrong:
(*f_ref)(4); // i even added more stars here like (****f_ref)(4)
f_ptr(3); // everything just works!
// all 4 statements above works just fine
// the only difference i found, as one would expect:
// f_ref = func2; // ERROR: read-only reference
f_ptr = func2; // works fine!
f_ptr(5);
return 0;
}
I used gcc version 4.7.2 in Fedora/Linux
UPDATE
My questions are:
Why function pointer does not require dereferencing?
Why dereferencing a function reference doesn't result in an error?
Is(Are) there any situation(s) where I must use one over the other?
Why f_ptr = &func; works? Since func should be decayed into a pointer?
While f_ptr = &&func; doesn't work (implicit conversion from void *)
Functions and function references (i.e. id-expressions of those types) decay into function pointers almost immediately, so the expressions func and f_ref actually become function pointers in your case. You can also call (***func)(5) and (******f_ref)(6) if you like.
It may be preferable to use function references in cases where you want the &-operator to work as though it had been applied to the function itself, e.g. &func is the same as &f_ref, but &f_ptr is something else.
"Why function pointer does not require dereferencing?"
Because the function identifier itself is actually a pointer to the function already:
4.3 Function-to-pointer conversion
§1 An lvalue of function type T can be converted to an rvalue of type “pointer to T.” The result is a pointer to the function.
"Why dereferencing a function reference doesn't result in an error?"
Basically you can look at defining a reference as defining an alias (alternative name). Even in the standard in 8.3.2 References in part addressing creating a reference to an object, you will find:
"a reference can be thought of as a name of an object."
So when you define a reference:
void (& f_ref)(int) = func;
it gives you the ability to use f_ref almost everywhere where it would be possible to use func, which is the reason why:
f_ref(1);
(*f_ref)(4);
works exactly the same way as using the func directly:
func(1);
(*func)(4);
See here.
The address-of operator acts like you would expect, as it points to a function but cannot be assigned. Functions are converted to function pointers when used as rvalues, which means you can dereference a function pointer any number of times and get the same function pointer back.
As there are good answers from other people here, there is no answer explaining why f_ptr = &&func; does not work. When you apply the addressof operator & to a variable/function, you get its address. The adress itself is an r-value/a temporary variable. You cannot take the address of a temporary.
But it seems that there is a type error. The message implicit conversion from void* is very compiler specific for this code. I guess you are using GCC/Clang. GCC/Clang offers the ability to take the address of labels like &&label. The resulting value is of type void*. Other compilers will output something like cannot take address of temporary or invalid syntax. When using these compilers this kind of error could have been hidden without any warning in special circumstances:
int main() {
int foo = 42;
foo:;
void* a = &foo; // take the address of a variable/function
void* b = &&foo; // take the address of a label
std::cout << *(int*)a << '\n';
goto *b;
};
But who would name everything the same?
Related
#include <iostream>
void PrintTheValue(int(*func)(int a));
int main(int argc, char **argv) {
PrintTheValue([](int a) {return a; });
return 0;
}
void PrintTheValue(int(*func)(int a)) {
std::cout << *func << std::endl;
}
In my concept of understanding the func, it would be a pointer to an int passed by value. But in this case I'm passing a lambda which doesn't seem to be called anywhere. (So there isn't any value at all?)
When I run this, it doesn't break the program, but instead printed 00EE6F80.
What does this address mean? I have no idea how to interpret it.
In my concept of understanding the func, it would be a pointer to an int passed by value.
func is a pointer to function, which takes an int and returns int.
But in this case I'm passing a lambda which doesn't seem to be called anywhere.
You're passing a lambda without capturing, which could convert to pointer to function implicitly. In PrintTheValue, *func, i.e dereference on the pointer results in a reference to function, and for being passed to operator<< of std::cout, it converts to function pointer again, then converts to bool with value true (as a non-null pointer), then you should get the result 1 (or true with the usage of std::boolalpha). If you want to call on func you could func(42) (or (*func)(42)).
A lambda is an unnamed function object of the closure type.
The crucial part for this case, this class does not overload the operator<<.
When you dereference the passed lambda in *func, there is no overload for operator<<, so it converts to nearest acceptable result which is bool (at first it reverts to a regular pointer).
The documentation:
Dereferencing a function pointer yields the lvalue identifying the pointed-to function
int f();
int (*p)() = f; // pointer p is pointing to f
(*p)(); // function f invoked through the function lvalue
// But no sense in *p
It should print 1 (since non-null pointer), which it does for me (g++). The language does allow us to do so, but there's no sense in dereferencing a pointer to function without calling the function. All the peculiarities of the function pointers are due to that they have one reasonable usage, so anything you do with them will support that usage - #Pete Becker
For more on Function Pointers check here, it will aid.
I am trying to cast a lambda function to a function pointer. However, the cast fails when the lambda has a non-void return type. Details see the code snippet.
Is it possible to cast fun2 into a generic function pointer which I can save for later usage?
Update: My intention is to cast all kinds of functions to a "generic function pointer" which can be saved in a std::map. Upon usage, I will cast it back to its original function type.
#include <iostream>
int fun3() { return 1; }
int main(int argc, char *argv[]) {
typedef void (*voidFunctionType)(void);
// Case 1: lambda, return type void
auto fun1 = []() { std::cout << "hello" << std::endl; };
// -> compiles
auto casted_fun1 = (voidFunctionType)fun1;
// Case 2: lambda, return type int
auto fun2 = []() { std::cout << "world" << std::endl; return -1;};
// -> error: invalid cast from type ‘main(int, char**)::<lambda()>’ to type ‘voidFunctionType {aka void (*)()}’
auto casted_fun2 = (voidFunctionType)fun2;
// Case 3: free function, return type int -> compiles
auto casted_fun3 = (voidFunctionType)fun3;
return 0;
}
The problem is that you are using C-style explicit casts. These are notoriously dangerous.
Here in this case the problem is that fun3 (in contrast to fun2) already decays to a function pointer of type int(*)().
You then cast it to void(*)(). This works because the C-style cast will try to do different C++ cast expressions until one works. In particular it will also try a reinterpret_cast.
reinterpret_cast<voidFunctionType>(fun3)
works, because reinterpret_cast can cast any function pointer to any other function pointer.
However, you are not allowed to call the function through the obtained pointer. Doing so causes your program to have undefined behavior. As you can see this cast is of very limited use and dangerous if you are not aware of it.
Don't use C-style casts, use static_cast<voidFunctionType>(fun3) instead and you will get the appropriate compile-time error in both cases.
You cannot use a function (whether free function or lambda) that returns one type as if it returned another (or no) type. Casting the lambda that returns int to void(*)() therefore doesn't make sense.
If you really want to save arbitrary function pointers you can make the lambda cast work by first converting it to a function pointer and then casting it to the destination function pointer type with a reinterpret_cast. I would still not use C style casts, because the reinterpret_cast will at least make it clear what kind of cast you are intending to do:
auto casted_fun2 = reinterpret_cast<voidFunctionType>(+fun2);
The unary + is a common trick to force lambda to function pointer conversion. Note however also that only lambdas without capture can be converted to function pointers.
As I explained above though, you must cast the pointer back to its original type before calling it, so you need to store the type information somewhere. I am not sure how you intend to do that, but you probably need to implement some extended version of std::function, see e.g. this question for how std::function does it.
There seems to be many relavent questions talking about pointer vs. reference, but I couldn't find what I want to know. Basically, an object is passed in by a reference:
funcA(MyObject &objRef) { ... }
Within the function, can I get a pointer to that object instead of the reference? If I treat the reference objRef as an alias to the MyObject, would &objRef actually give me a pointer to the MyObject? It doesn't seem likely. I am confused.
Edit: Upon closer examination, objRef does give me back the pointer to object that I need - Most of you gave me correct info/answer, many thanks. I went along the answer that seems to be most illustrative in this case.
Yes, applying the address-of operator to the reference is the same as taking the address of the original object.
#include <iostream>
struct foo {};
void bar( const foo& obj )
{
std::cout << &obj << std::endl;
}
int main()
{
foo obj;
std::cout << &obj << std::endl;
bar( obj );
return 0;
}
Result:
0x22ff1f
0x22ff1f
Any operator applied to a reference will actually apply to the object it refers to (§5/5 [expr]); the reference can be thought of as another name for the same object. Taking the address of a reference will therefore give you the address of the object that it refers to.
It as actually unspecified whether or not a reference requires storage (§8.3.2/4 [dcl.ref]) and so it wouldn't make sense to take the address of the reference itself.
As an example:
int x = 5;
int& y = x;
int* xp = &x;
int* yp = &y;
In the above example, xp and yp are equal - that is, the expression xp == yp evaluates to true because they both point to the same object.
The general solution is to use std::addressof, as in:
#include <type_traits>
void foo(T & x)
{
T * p = std::addressof(x);
}
This works no matter whether T overloads operator& or not.
Use the address operator on the reference.
MyObject *ptr = &objRef;
Use the address-of (&) operator on the reference.
&objRef
Like any other operator used on a reference, this actually affects the referred-to object.
As #Kerrek points out, since the operator affects the referred-to object, if that object has an overloaded operator& function, this will call it instead and std::address_of is needed to get the true address.
In C++, a reference is a restricted type of pointer. It can only be assigned once and can never have a NULL value.
References are most useful when used to indicate that a parameter to a function is being Passed by Reference where the address of the variable is passed in. Without a Reference, Pass By Value is used instead.
Will the following work as expected?:
struct A {};
struct B: public A {
int x;
};
void f( B* o ) {
std::cout << o->x << std::endl;
}
int main () {
B b;
b.x = 5;
reinterpret_cast<void(*)(A*)>(f)( &b );
}
Its undefined behaviour to use such pointer after cast:
Any pointer to function can be converted to a pointer to a different function type. Calling the function through a pointer to a different function type is undefined, but converting such pointer back to pointer to the original function type yields the pointer to the original function.
From http://en.cppreference.com/w/cpp/language
So the answer to your question is actually positive - you are allowed to cast but nothing more.
You might ask "what is the point of only casting?" - this is usefull when you want to store various functions in single collection.
See 5.2.10/6 [expr.reinterpret.cast]:
A function pointer can be explicitly converted to a function pointer of a different type. The effect of calling a function through a pointer to a function type that is not the same as the type used in the definition of the function is undefined.
That said, note as an example that C++ allows you to dereference a null pointer, so maybe allowed is not the right term.
The following command compiles too:
reinterpret_cast<void(*)(A*, int)>(f)( &b, 42 );
It is allowed, as well as the one in the question, no matter if it works as expected or not (it mostly depends on your expectations, as noted by #luk32 in the comments).
The answer to your question would be yes, the cast is allowed, but the invokation of the function through the new pointer leads to an undefined behavior.
There seems to be many relavent questions talking about pointer vs. reference, but I couldn't find what I want to know. Basically, an object is passed in by a reference:
funcA(MyObject &objRef) { ... }
Within the function, can I get a pointer to that object instead of the reference? If I treat the reference objRef as an alias to the MyObject, would &objRef actually give me a pointer to the MyObject? It doesn't seem likely. I am confused.
Edit: Upon closer examination, objRef does give me back the pointer to object that I need - Most of you gave me correct info/answer, many thanks. I went along the answer that seems to be most illustrative in this case.
Yes, applying the address-of operator to the reference is the same as taking the address of the original object.
#include <iostream>
struct foo {};
void bar( const foo& obj )
{
std::cout << &obj << std::endl;
}
int main()
{
foo obj;
std::cout << &obj << std::endl;
bar( obj );
return 0;
}
Result:
0x22ff1f
0x22ff1f
Any operator applied to a reference will actually apply to the object it refers to (§5/5 [expr]); the reference can be thought of as another name for the same object. Taking the address of a reference will therefore give you the address of the object that it refers to.
It as actually unspecified whether or not a reference requires storage (§8.3.2/4 [dcl.ref]) and so it wouldn't make sense to take the address of the reference itself.
As an example:
int x = 5;
int& y = x;
int* xp = &x;
int* yp = &y;
In the above example, xp and yp are equal - that is, the expression xp == yp evaluates to true because they both point to the same object.
The general solution is to use std::addressof, as in:
#include <type_traits>
void foo(T & x)
{
T * p = std::addressof(x);
}
This works no matter whether T overloads operator& or not.
Use the address operator on the reference.
MyObject *ptr = &objRef;
Use the address-of (&) operator on the reference.
&objRef
Like any other operator used on a reference, this actually affects the referred-to object.
As #Kerrek points out, since the operator affects the referred-to object, if that object has an overloaded operator& function, this will call it instead and std::address_of is needed to get the true address.
In C++, a reference is a restricted type of pointer. It can only be assigned once and can never have a NULL value.
References are most useful when used to indicate that a parameter to a function is being Passed by Reference where the address of the variable is passed in. Without a Reference, Pass By Value is used instead.