C++ -- Questions about function pointers - c++

I have written the following code:
#include "stdafx.h"
#include <iostream>
using namespace std;
double funcA()
{
return 100.0;
}
int g(double (*pf)())
{
cout << (*pf)() << endl;
return 0;
}
int g2(double pf())
{
cout << pf() << endl;
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
g(&funcA); // case I
g(funcA); // case II
g2(funcA); // case III
g2(&funcA); // case IV
return 0;
}
I have run the above code on VS2008 and each function call returns '100'.
Here is the question:
Q1> Is there any problem in the code?
Q2> It seems that C++ doesn't make difference between *pf and pf. Is that correct?
Thank you

C++ does, in fact, make a distinction between the types double() and double(*)(), but the difference is subtle. When you pass a function type as an argument to a function, the function-type automatically "degrades" to a function pointer. (This is similar, I suppose, to how an array type degrades to a pointer type when passed as a function argument.)
However, a function type and a function-pointer type are still different types, according to the C++ type-system. Consider the following case:
void g() { }
template <class F>
struct Foo
{
Foo(const F& f) : func(f)
{ }
void operator()() { func(); }
F func;
};
int main ()
{
Foo<void()> f(g);
f();
}
This should fail to compile, since you cannot declare a function type as an automatic variable. (Remember, functions are not first-class objects in C++.) So the declaration F func; is invalid. However, if we change our main function to instead instantiate the template using a function pointer, like so:
int main ()
{
typedef void(*function_pointer)();
Foo<function_pointer> f(g);
f();
}
...now it compiles.

The following functions are identical:
int g(double (*pf)())
{
cout << (*pf)() << endl;
return 0;
}
int g2(double pf())
{
cout << pf() << endl;
return 0;
}
Dereferencing a function pointer (as shown in g) is the same as calling that function's name.
Q2> It seems that C++ doesn't make
difference between *pf and pf. Is that
correct?
There is a difference between *pf and pf (as variables). If pf is a function, *pf and pf() are identical (Note the parentheses).

With most modern compilers, there is no difference between "(*variable)." and "variable->". However, one must check the class in use to see if it overrides the dereference operator.
Many programmers use typedef when defining function pointers, primarily to make reading easier. Also, the double pf() syntax may be prone to readability errors and can get confused with executing a function on parameter line.

There's no problem or difference in the code you posted. However, if you are writing templates which take functors, you should use the syntax in g2. Consider the following:
template<typename Iter, typename Func>
void for_each(Iter begin, Iter end, Func functor)
{
for(; begin != end; ++begin)
{
functor(*begin);
}
}
Note that if you put the dereference operator before functor, you limit the utility of the algorithm you have written to function pointers. However, if you don't put that there, someone can pass an STL functor, such as something returned by std::bind2nd.
Therefore I would overall recommend using the second (without *) syntax where possible.

Consider the following piece of code
void pf();
void (&prf)() = pf; // OK, bind prf to pf
void (&prf)() = &pf; // ill-formed, can't bind prf to an function pointer value
On the other hand
void (*ppf)() = pf; // OK, function decays to a pointer
void (*ppf)() = &pf; // OK, pointer assigned to a pointer
So there is an implicit conversion from a function to a pointer (which is called "decay"). This also makes you able to say ***...***pf - arbitrarily many times dereference it - in each step a function to pointer conversion occurs which undoes the effect of the previous dereference.
In function parameter lists, a T f() and a T (*f)() are equivalent ways (except for spelling) of declaring a parameter
void f(void g()); // g has type void (*)()
void f(void (*g)()); // g has type void (*)()
A reference will inhibit this parameter type adjustment
void f(void (&g)()); // g has *not* the type void (*)()
This is exactly the same as for array declared parameters: Parameters are never arrays, but they will always be pointers, if they were declared as being arrays.

Related

Why does the compiler complain for ambiguity in overloaded function? [duplicate]

Does declaring something like the following
void foo(int x) { std::cout << "foo(int)" << std::endl; }
void foo(const int &x) { std::cout << "foo(const int &)" << std::endl; }
ever make sense? How would the caller be able to differentiate between them? I've tried
foo(9); // Compiler complains ambiguous call.
int x = 9;
foo(x); // Also ambiguous.
const int &y = x;
foo(y); // Also ambiguous.
The intent seems to be to differenciate between invocations with temporaries (i.e. 9) and 'regular' argument passing. The first case may allow the function implementation to employ optimizations since it is clear that the arguments will be disposed afterwards (which is absolutely senseless for integer literals, but may make sense for user-defined objects).
However, the current C++ language standard does not offer a way to overload specifically for the 'l/r-valueness' of arguments - any l-value being passed as argument to a function can be implicitly converted to a reference, so the ambiguity is unavoidable.
C++11 introduces a new tool for a similar purpose — using r-value references, you can overload as follows
void foo(int x) { ... }
void foo(const int &&x) { ... }
... and foo(4) (a temporary, r-value passed as argument) would cause the compiler to pick the second overload while int i = 2; foo(i) would pick the first.
(note: even with the new toolchain, it is not possible to differentiate between the cases 2 and 3 in your sample!)
You could do this with a template:
template<typename T> void foo(T x) { ... }
Then you can call this template by value or by reference:
int x = 123;
foo<int>(x); // by value
foo<int const&>(x); // by refernce
How would the caller be able to differentiate between them?
It cannot be differentiated in this case. Both the overloaded functions have the same type of primitive data type as the argument. And taking by reference doesn't count for a different type.
You can use static_cast to explicitly select the overload to be called:
#include <iostream>
void foo(int x) { std::cout << "foo(int)" << std::endl; }
void foo(const int &x) { std::cout << "foo(const int &)" << std::endl; }
int main()
{
int x = 0;
auto f1 = static_cast< void(*)(int) >(foo);
f1(x);
auto f2 = static_cast< void(*)(const int&) >(foo);
f2(x);
}
However, you should ask yourself why you provided those two overloads in the first place. Either you are fine with making a copy or you are not. Both at the same time? Why? Also making it necessary for the caller to explicitly select the overload defeats the purpse of function overloading. If you really want that consider to supply two functions instead:
void foo_copying(int x) { std::cout << "foo(int)" << std::endl; }
void foo_non_copying(const int &x) { std::cout << "foo(const int &)" << std::endl; }
Not in C++. Functional languages such as Erlang and Haskell get closer by allowing you to specify function overloads based on parameter value, but most imperative languages including C++ require overloading based on method signature; that is, the number and type of each parameter and the type of the return value.
The const keyword in the signature defines not the type of the parameter, but its mutability within the function; a "const" parameter will generate a compiler error if modified by the function or passed by reference to any function that doesn't also use const.
The compiler can't.
Both definitions of foo can be used for all 'variants' of int.
In the first foo, a copy of the int is made. Copying an int is always possible.
In the second foo, a reference to a const int is passed. Since any int can be cast to a const int, a reference to it can be passed as well.
Since both variants are valid in all cases, the compiler can't choose.
Things become different if you e.g. use the following definition:
void foo (int &x);
Now calling it with foo(9) will take the first alternative, since you can't pass 9 as a non-const int reference.
Another example, if you replace int by a class where the copy constructor is private, then the caller can't make a copy of the value, and the first foo-variant will not be used.

Why can I bind a function taking by-value argument to a std::function taking a lvalue reference?

After digging to find the source of a bug, I was surprised to discover that the following seems to be legal C++11 (compiles fine with GCC/clang with Wall). In particular, why can I assign f1, which takes its argument by value to a RefFunction which expects an argument by reference ?
I tried googling for an explanation, but didn't find anything relevant, probably because I don't know exactly what to google for. I'd really appreciate if someone can guide me through why this is legal.
#include <iostream>
using namespace std;
void f1(int val) {
val = 1;
}
void f2(int& val) {
val = 2;
}
using RefFunction = std::function<void(int&)>;
int main()
{
using namespace std::placeholders;
int val = 42;
// I was expecting a compile error here telling me that f1 doesn't
// have the right signature (int instead of int&)
RefFunction f = f1;
f(val);
cout << val << endl; // prints 42
// This makes sense, f2 takes argument by reference
f = f2;
f(val);
cout << val << endl; // prints 2
return EXIT_SUCCESS;
}
Setting aside the standardese for the time being, think in terms of the following:
void f1(int val) {
val = 1;
}
void f2(int& val) {
val = 2;
}
void WrapperFunction(int& val)
{
f1(val); // Should be OK
f2(val); // Should be OK.
}
The compiler should not have any problems with the above code. If you think of WrapperFunction analogous to a std::function, the compiler should not have any problem regardless of whether the std::function is constructed with f1 or f2.
The template argument of std::function enforces the manner in which the std::function may be called; therefore a RefFunction can only be called with an lvalue of type int or something that can be implicitly converted to an lvalue of type int. It will then call the underlying function, f1 or f2. A function that receives a reference to int can always use that reference to call a function that takes int by value; the int referred to will simply be copied.
In general std::function<R(T...)> can store a callable with any signature as long as it's true that the T... parameters of the std::function's function call operator can actually be used to call the underlying callable. The signatures don't need to match exactly.

difference between void(int) & void (*)(int)

I know void (*)(int) is to function pointer but what is void(int)?
It's used for std::function template.
Say I have a function void fun(int){} : decltype(&fun) gives void(*)(int) but decltype(fun) gives void(int)
If T is a type, then T* denotes the type "pointer-to-T".
The type void(int) is a function type, it's the type of a function taking one int and returning void. For example, it is the type of f if f is declared as void f(int);
If T = void(int), then T* is spelled void(*)(int), so the latter is the type of a function pointer. You can also form a reference to a function, which is T& = void(&)(int); this is occasionally more useful (e.g. you can take the address of a function lvalue).
Aside note: Function lvalues decay to their function pointer very easily. You can call a function either via a function lvalue or via a function pointer. When used as an operand for the indirection operator (*), the function value decays, so you can dereference the pointer again and again:
printf("Hello world\n"); // OK
(*printf)("Hello world\n"); // also OK
(****printf)("Hello world\n"); // four-star programmer
Some of the only times that a function does not decay is when used as the operand of the address-of operator, or when bound to a reference:
void f(int); // our example function
void(*p1)(int) = &f; // no decay of "f" here
void(*p2)(int) = f; // "f" decays
void(&r1)(int) = f; // no decay of "f" here
void g(void(&callback)(int), int n) {
callback(n);
}
g(f, 10); // no decay of "f" here
template <typename F, typename ...Args>
decltype(auto) h(F&& callback, Args&&... args) {
return std::forward<F>(callback)(std::forward<Args>(args)...);
}
h(f, 10); // no decay of "f" here
void (*whatever)(int)
should be read as: whatever is a pointer, pointing to a function, that accepts one int as argument, and returns nothing (ie., void).
void whatever(int)
should be read as: whatever is a function (NOT a pointer), that accepts one int as argument, and returns nothing (ie., void)
Once the pointer to a function is initialized to point to a valid function (one that satisfies the prototype), then you can invoke the function either through its "real" name, or through the pointer.
Pointers to functions are very useful - they're variables, just like anything else, so you can pass them around to other functions (see e.g. qsort()), you can put them in structs, etc..
Given this, the following code is valid:
#include <stdio.h>
void myfun(int x) {
printf("The value of X is %d\n", x);
}
int main() {
void (*myfunp)(int);
myfunp = &myfun;
myfun(13);
myfunp(12);
return 0;
}
void(*)(int) should be read as type of a pointer which is pointing to a function, that accepts one int as argument, and returns nothing.
For understanding more on function to pointer and its usage please check here: http://www.cprogramming.com/tutorial/function-pointers.html

function type vs. function pointer type

I'm trying to understand the difference between the following two blocks of code:
void f(int (*func)(int))
{
func(5);
}
and
void g(int (func)(int))
{
func(5);
}
Both functions work in the same way given the following code:
int blah(int a)
{
cout << "hello" << endl;
return 0;
}
int main()
{
f(blah);
g(blah);
return 0;
}
However, if I write the following code:
int (*foo)(int);
int (goo)(int);
foo = blah;
goo = blah;
I get a compile error for goo = blah. But in the first example, I could call make the function call g(blah) which appears to be quite similar to goo = blah. Why does one work and not the other?
Somewhat confusingly, you can declare a function to take a function as a parameter (even though that makes no sense), and the effect is to make the parameter a function pointer. This is similar to the way you can declare a function parameter that looks like an array, but is actually a pointer.
The function argument can be the name of the function, with or without a & to explicitly take its address. If you omit the &, then there's an implicit function-to-pointer conversion. Again, this is similar to passing a (pointer to) an array, where the implicit array-to-pointer conversion means you only need to write the array's name, rather than &array[0].
That rule doesn't apply when declaring variables; int goo(int); (with or without unnecessary parentheses around goo) declares a function, not a pointer, and you can't assign to functions.
It's analogous to the difference between an array and a pointer, e.g. if you have:
char *foo;
char bar[N];
you can do:
foo = bar;
but you can't do:
bar = foo;
When the function type is used in an argument declaration, it's translated to the equivalent function pointer, just as declaring:
void fun(int arr[]);
is translated to:
void fun(int *arr);

Function Overloading Based on Value vs. Const Reference

Does declaring something like the following
void foo(int x) { std::cout << "foo(int)" << std::endl; }
void foo(const int &x) { std::cout << "foo(const int &)" << std::endl; }
ever make sense? How would the caller be able to differentiate between them? I've tried
foo(9); // Compiler complains ambiguous call.
int x = 9;
foo(x); // Also ambiguous.
const int &y = x;
foo(y); // Also ambiguous.
The intent seems to be to differenciate between invocations with temporaries (i.e. 9) and 'regular' argument passing. The first case may allow the function implementation to employ optimizations since it is clear that the arguments will be disposed afterwards (which is absolutely senseless for integer literals, but may make sense for user-defined objects).
However, the current C++ language standard does not offer a way to overload specifically for the 'l/r-valueness' of arguments - any l-value being passed as argument to a function can be implicitly converted to a reference, so the ambiguity is unavoidable.
C++11 introduces a new tool for a similar purpose — using r-value references, you can overload as follows
void foo(int x) { ... }
void foo(const int &&x) { ... }
... and foo(4) (a temporary, r-value passed as argument) would cause the compiler to pick the second overload while int i = 2; foo(i) would pick the first.
(note: even with the new toolchain, it is not possible to differentiate between the cases 2 and 3 in your sample!)
You could do this with a template:
template<typename T> void foo(T x) { ... }
Then you can call this template by value or by reference:
int x = 123;
foo<int>(x); // by value
foo<int const&>(x); // by refernce
How would the caller be able to differentiate between them?
It cannot be differentiated in this case. Both the overloaded functions have the same type of primitive data type as the argument. And taking by reference doesn't count for a different type.
You can use static_cast to explicitly select the overload to be called:
#include <iostream>
void foo(int x) { std::cout << "foo(int)" << std::endl; }
void foo(const int &x) { std::cout << "foo(const int &)" << std::endl; }
int main()
{
int x = 0;
auto f1 = static_cast< void(*)(int) >(foo);
f1(x);
auto f2 = static_cast< void(*)(const int&) >(foo);
f2(x);
}
However, you should ask yourself why you provided those two overloads in the first place. Either you are fine with making a copy or you are not. Both at the same time? Why? Also making it necessary for the caller to explicitly select the overload defeats the purpse of function overloading. If you really want that consider to supply two functions instead:
void foo_copying(int x) { std::cout << "foo(int)" << std::endl; }
void foo_non_copying(const int &x) { std::cout << "foo(const int &)" << std::endl; }
Not in C++. Functional languages such as Erlang and Haskell get closer by allowing you to specify function overloads based on parameter value, but most imperative languages including C++ require overloading based on method signature; that is, the number and type of each parameter and the type of the return value.
The const keyword in the signature defines not the type of the parameter, but its mutability within the function; a "const" parameter will generate a compiler error if modified by the function or passed by reference to any function that doesn't also use const.
The compiler can't.
Both definitions of foo can be used for all 'variants' of int.
In the first foo, a copy of the int is made. Copying an int is always possible.
In the second foo, a reference to a const int is passed. Since any int can be cast to a const int, a reference to it can be passed as well.
Since both variants are valid in all cases, the compiler can't choose.
Things become different if you e.g. use the following definition:
void foo (int &x);
Now calling it with foo(9) will take the first alternative, since you can't pass 9 as a non-const int reference.
Another example, if you replace int by a class where the copy constructor is private, then the caller can't make a copy of the value, and the first foo-variant will not be used.