When I'm passing function as parameter to other functions in c++ , do I have to specify it as
void callOtherFunctions(void f());
or
void callOtherFunctions(void (*f)());
I have no idea what happens under the hood , so I tried running both versions with a simple program as below , replacing the necessary part for 2nd run.
#include <iostream>
using namespace std;
void printHello();
void callOtherFunctions(void f());
int main() {
callOtherFunctions(printHello);
return 0;
}
void printHello(){
std::cout<<"\n Hello World";
}
void callOtherFunctions(void f()){
for (int i=0;i<5;++i){
f();
}
}
and to my surprise , both execute with same output and no warnings. So which is the preferred way , or correct way ( in case I'm doing something wrong ). And what actually happens in each case , when I pass pointer - does it executes address function there and when I pass function - does it copies down whole function there? or something else?
Here is Ideone Link
void callOtherFunctions(void f());
and
void callOtherFunctions(void (*f)());
are identical. Quoting N1570,
§6.7.6.3/8 A declaration of a parameter as "function returning type"
shall be adjusted to "pointer to function returning type", as in
6.3.2.1.
I would prefer the function pointer syntax because more people would be familiar with it and it's explicit what you mean. To answer your second question, a conversion also happens in certain cases (informally known as "decay"):
§6.3.2.1/4 A function designator is an expression that has function
type. Except when it is the operand of the sizeof operator, the
_Alignofoperator,65) or the unary & operator, a
function designator with type "function returning type" is converted to an expression that has type "pointer to function returning type".
Function parameter declarations are somewhat unusual; the compiler will adjust some of the declared types. This is one of them: function parameters of function type are adjusted to the corresponding pointer type.
Other common adjustments to function parameters are array to pointer type, and removing top-level const:
int foo(int a[5]); // a is a pointer
int foo(const int a); // foo() can be called with a non-const int argument.
Related
void(*)(void) is a function pointer while I suppose void(void) is also a way to represent function type. It is used as template parameter in std::function <functional>
What is void(void) and how it is different from void(*)(void)?
What is void(void) and how it is different from void(*)(void)?
They are distinct types. Although the former(void(void)) can be implicitly converted to the latter(void(*)(void)) in many contexts.
The type void(void) is called a function type. The following are also function types:
int (int, int) //this is a function type
void(int) //this is a function type as well
On the other hand, void (*)(void) is a pointer to a function type. That is, it is a pointer that points to a function with 0 parameters and return type of void.
TL;DR
The void(void) is a specification of a function type, it's
signature.
The void(*)(void) is a pointer to function.
These are distinct.
First, let's start by saying, that sometimes the void(void) will be automatically treated as a pointer to function (i.e. in a parameter list). We still can be explicit and use the void(*)(void), but the void(void) will be an equivalent in these cases.
// Here, we explicitly state that the f is a pointer to function
void foo(void (*f)(void), int i);
// Equivalent, f is automatically treated as a pointer to the function
void foo(void f(void), int i);
This will not be the case for the mentioned std::function for example. The types of the two are different, yet may have similar behavior (i.e. we can use the function call operator on a pointer to function).
void bar();
// Prints 1
std::cout << std::is_same<void(void), decltype(bar)>::value << '\n';
// Prints 1 as well
// Note the pointer type specifier
std::cout << std::is_same<void(*)(void), decltype(bar)*>::value << '\n';
// Prints 0
// Note the absence of the pointer type specifier
std::cout << std::is_same<void(*)(void), decltype(bar)>::value << '\n';
And particularly:
// Ok
std::function<decltype(bar)> fn1 = bar;
// error: variable ‘std::function<void (*)()> fn2’ has initializer but incomplete type
std::function<decltype(bar)*> fn2 = bar;
Note, that we can however "store" a pointer to a member function in std::function, but even then the template's parameter still won't be of a pointer to function type, but a plain function signature.
struct MyType {
void func(int) {}
};
int main() {
// Note, we can't have a member function without an instance of the type
// Thus we specify the usually implicit first param and the explicit int param
std::function<void(MyType&, int)> fn_mem = &MyType::func;
MyType my_object;
fn_mem(my_object, 21);
}
For more on std::function please refer to the reference. In short, the use of the std::function instead of the function pointers has the same moto as using the smart pointers instead of the raw pointers.
You may wonder on other uses of the void(void) or int(int) style function type specifications, so here's another example you may see often:
using func_t = int(int);
// func_ptr_func return a pointer to the func_t type alias
func_t* func_ptr_func();
N.B. unlike in the case of a parameter, the compiler won't treat the function type in a return as a pointer to function type. Thus, we must explicitly specify the pointer type in case of the return.
// Here, baz is a function that doesn't take any agruments
// And returns a pointer to a function that takes an int argument and "returns" void
void (*baz())(int);
for void fun(){}, std::is_same_v<void(void)>, decltype(fun)> is true; and std::is_same_v<void(*)(void)>, decltype(&fun)> is true. In fact, those are their real types. However, the standard approve you convert an object that has type void(void) to void(*)(void) implicitly (so you can even write (******funptr)()), that's why we always confuse them.
On this page I found a good example of function pointers in C++ (as well as of functors, but this question isn't about functors). Below is some copypasta from that page.
#include <iostream>
double add(double left, double right) {
return left + right;
}
double multiply(double left, double right) {
return left * right;
}
double binary_op(double left, double right, double (*f)(double, double)) {
return (*f)(left, right);
}
int main( ) {
double a = 5.0;
double b = 10.0;
std::cout << "Add: " << binary_op(a, b, add) << std::endl;
std::cout << "Multiply: " << binary_op(a, b, multiply) << std::endl;
return 0;
}
I understand the code in general terms, but there are a couple of things that I've always found confusing. Function binary_op() takes a function pointer *f, but when it's used, for example on line 19 binary_op(a, b, add), the function symbol add is passed in, not what one would think of as its pointer, &add. Now you may say that this is because the symbol add is a pointer; it's the address of the bit of code corresponding to the function add(). Very well, but then there still seems to be a type discrepancy here. The function binary_op() takes *f, which means f is a pointer to something. I pass in add, which itself is a pointer to code. (Right?) So then f is assigned the value of add, which makes f a pointer to code, which means that f is a function just like add, which means that f should be called like f(left, right), exactly how add should be called, but on line 12, it's called like (*f)(left, right), which doesn't seem right to me because it would be like writing (*add)(left, right), and *add isn't the function, it's the first character of the code that add points to. (Right?)
I know that replacing the original definition of binary_op() with the following also works.
double binary_op(double left, double right, double f(double, double)) {
return f(left, right);
}
And in fact, this makes much more sense to me, but the original syntax doesn't make sense as I explained above.
So, why is it syntactically correct to use (*f) instead of just f? If the symbol func is itself a pointer, then what precisely does the phrase "function pointer" or "pointer to a function" mean? As the original code currently stands, when we write double (*f)(double, double), what kind of thing is f then? A pointer to a pointer (because (*f) is itself a pointer to a bit of code)? Is the symbol add the same sort of thing as (*f), or the same sort of thing as f?
Now, if the answer to all of this is "Yeah C++ syntax is weird, just memorise function pointer syntax and don't question it.", then I'll reluctantly accept it, but I would really like a proper explanation of what I'm thinking wrong here.
I've read this question and I think I understand that, but haven't found it helpful in addressing my confusion. I've also read this question, which also didn't help because it doesn't directly address my type discrepancy problem. I could keep reading the sea of information on the internet to find my answer but hey, that's what Stack Overflow is for right?
This is because C function pointer are special.
First of, the expression add will decay into a pointer. Just like reference to array will decay into a pointer, reference to function will decay into a pointer to function.
Then, the weird stuff it there:
return (*f)(left, right);
So, why is it syntactically correct to use (*f) instead of just f?
Both are valid, you can rewrite the code like this:
return f(left, right);
This is because the dereference operator will return the reference to the function, and both a reference to a function or a function pointer are considered callable.
The funny thing is that a function reference decay so easily that it will decay back into a pointer when calling the dereference operator, allowing to dereference the function as many time as you want:
return (*******f)(left, right); // ah! still works
As the original code currently stands, when we write double (*f)(double, double), what kind of thing is f then?
The type of f is double (*)(double, double) i.e. it is a pointer to a function of type double(double,double).
because (*f) is itself a pointer
It is not.
Q: What do you get when you indirect through a pointer (such as in *f)? A: You get an lvalue reference. For example, given an object pointer int* ptr, the type of the expression *ptr is int& i.e. lvalue reference to int.
The same is true for function pointers: When you indirect through a function pointer, you get an lvalue reference to the pointed function. In the case of *f, the type is double (&)(double, double) i.e. reference to function of type double(double,double).
Is the symbol add the same sort of thing as (*f), or the same sort of thing as f?
The unqualified id expression add is the same sort of thing as *f i.e. it is an lvalue:
Standard draft [expr.prim.id.unqual]
... The expression is an lvalue if the entity is a function ...
the function symbol add is passed in, not what one would think of as its pointer, &add. Now you may say that this is because the symbol add is a pointer;
No. That's not the reason.
add is not a pointer. It is an lvalue. But lvalues of function type implicitly convert to a pointer (this is called decaying):
Standard draft [conv.func]
An lvalue of function type T can be converted to a prvalue of type “pointer to T”. The result is a pointer to the function.
As such, the following are semantically equivalent:
binary_op(a, b, add); // implicit function-to-pointer conversion
binary_op(a, b, &add); // explicit use of addressof operator
So, why is it syntactically correct to use (*f) instead of just f?
Turns out that calling a function lvalue has the same syntax as calling a function pointer:
Standard draft [expr.call]
A function call is a postfix expression followed by parentheses containing a possibly empty, comma-separated list of initializer-clauses which constitute the arguments to the function.
The postfix expression shall have function type or function pointer type.
For a call to a non-member function or to a static member function, the postfix expression shall either be an lvalue that refers to a function (in which case the function-to-pointer standard conversion ([conv.func]) is suppressed on the postfix expression), or have function pointer type.
These are all the same function call:
add(parameter_list); // lvalue
(*f)(parameter_list); // lvalue
(&add)(parameter_list); // pointer
f(parameter_list); // pointer
P.S. These two declarations are equivalent:
double binary_op(double, double, double (*)(double, double))
double binary_op(double, double, double (double, double))
This is because of the following rule, which is complementary to the implicit decay into function pointer:
Standard draft [dcl.fct]
The type of a function is determined using the following rules.
The type of each parameter (including function parameter packs) is determined from its own decl-specifier-seq and declarator.
After determining the type of each parameter, any parameter of type “array of T” or of function type T is adjusted to be “pointer to T” ...
First of all a function parameter specified as a function declaration is adjusted to pointer to the function when the compiler determinates the type of the parameter. So for example following function declarations
void f( void h() );
void f( void ( *h )() );
are equivalent and declare the same one function.
Consider the following demonstrative program
#include <iostream>
void f( void h() );
void f( void ( *h )() );
void h() { std::cout << "Hello Ray\n"; }
void f( void h() ) { h(); }
int main()
{
f( h );
}
From the c++ 17 Standard (11.3.5 Functions):
5 The type of a function is determined using the following rules. The
type of each parameter (including function parameter packs) is
determined from its own decl-specifier-seq and declarator. After
determining the type of each parameter, any parameter of type “array
of T” or of function type T is adjusted to be “pointer to T”.
On the other hand, according to the C++ 17 Standard
9 When there is no parameter for a given argument, the argument is
passed in such a way that the receiving function can obtain the value
of the argument by invoking va_arg (21.11). [ Note: This paragraph
does not apply to arguments passed to a function parameter pack.
Function parameter packs are expanded during template instantiation
(17.6.3), thus each such argument has a corresponding parameter when a
function template specialization is actually called. — end note ] The
lvalue-to-rvalue (7.1), array-to-pointer (7.2), and function-to-pointer (7.3)
standard conversions are performed on the argument expression
So what is the difference between these two declarations
void f( void h() );
void f( void ( *h )() );
For the first declaration you may consider the parameter h within the function body like a typedef for a function pointer.
typedef void ( *H )();
For example
#include <iostream>
void f( void h() );
void f( void ( *h )() );
void h() { std::cout << "Hello Ray\n"; }
typedef void ( *H )();
void f( H h ) { h(); }
int main()
{
f( h );
}
According to the C++ 17 Standard (8.5.1.2 Function call)
1 A function call is a postfix expression followed by parentheses
containing a possibly empty, comma-separated list of
initializer-clauses which constitute the arguments to the function.
The postfix expression shall have function type or function pointer
type.
So you may also define the function like
void f( void h() ) { ( *h )(); }
Or even like
void f( void h() ) { ( ******h )(); }
because when the operator * is applied to a function name then the function name is implicitly convereted to pijnter to the function.
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
Do these lines mean the same? Both works without any warning messages!
int (*pFunc)() = func1; // I learned this is right.
int (*pFunc)() = &func1; // Works well with an ampersand too.
Why do I have to put an ampersand in this case? Without it, doesn't work!
int (CMyClass::*pMemberFunc)() = &CMyClass::memberFunc1;
Why do I have to specify namespace for functions in Classes even if the type of the function pointer matches exactly?
int (*pMemberFunc)() = CMyClass::memberFunc1; // Compiler error
int (*pMemberFunc)() = &CMyClass::memberFunc1; // Compiler error
Why can't I specify namespace in this case?
namespace myNamespace {
int func1() {}
}
int (myNamespace::*pFunc)() = myNamespace::func1; // Compiler error
int (myNamespace::*pFunc)() = &myNamespace::func1; // Compiler error
int (*pFunc)() = &myNamespace::func1; // Works!
Your first question, legalese of the Standard:
A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed
in parentheses. [Note: that is, the expression &(qualified-id), where the qualified-id is enclosed in
parentheses, does not form an expression of type “pointer to member.” Neither does qualified-id, because
there is no implicit conversion from a qualified-id for a non-static member function to the type “pointer to
member function” as there is from an lvalue of function type to the type “pointer to function” (4.3). Nor is
&unqualified-id a pointer to member, even within the scope of the unqualified-id’s class. —end note ]
While it seems inconsistent at first, I do like the fact that it makes the semantics for pointers to members (be them functions or not) equivalent. This certainly has benefits when dealing with templates and decltype.
For the second question, you scope the pointer variable with CMyClass because yours is not a simple "() -> int" function: memberFunc1() is implicitly passed a CmyClass* argument you normally refer to as "this".
If you could truly pass nothing, you'd be missing information (and possibly crash) for the method to do its job correctly. If you're accustomed to "delegates" in other languages, do remember these can optionally store a "Target" pointer to the "this" object if the method is not static/global.
As for the third, it's a free standing function, so it's truly () -> int, but you're attempting to scope your pointer to the namespace, when in fact you're not declaring your variable inside the namespace block.
While the namespace certainly alters how symbols are searched for, it doesn't affect the convention call of the function at all.
1) about Q1, looking at the following code, as the func1 is a right-value of the function, so with or without "&" doesn't change the actual function address.
Look at the following code:
#include <stdio.h>
void foo(){
printf("foo called\n");
}
int main(){
printf("%p\n", foo);
printf("%p\n", &foo);
void (*FUNC) ();
FUNC = foo;
FUNC();
printf("address %p\n", FUNC);
printf("address %p\n", &FUNC);
return 0;
}
output is
0x101406eb0
0x101406eb0
foo called
address 0x101406eb0
address 0x7fff5e7f9a80
Q2 & Q3 )
Pointers to Member Functions Are Not Pointers
You can refer it here
https://www.safaribooksonline.com/library/view/c-common-knowledge/0321321928/ch16.html
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);