Reputation: 36393
Take the following C/C++ code:
#include <stdlib.h>
int inc(int i) { return i+1; } // int→int, like abs()
// baz is bool→(int→int)
int (*baz(bool b))(int) { return b ? &abs : &inc; }
int main() {
int (*foo(bool))(int); // foo is &(bool→(int→int))
foo = baz;
}
Attempting to compile this (gcc or g++) gives:
$ g++ test.cc
test.cc: In function ‘int main()’:
test.cc:9: error: assignment of function ‘int (* foo(bool))(int)’
test.cc:9: error: cannot convert ‘int (*(bool))(int)’ to ‘int (*(bool))(int)’ in assignment
Check for yourself: the two types it claims it cannot convert between are exactly the same. Why then is it claiming that they are incompatible?
EDIT 1: The problem disappears when using typedef
s (as is recommended), like so:
int main() {
typedef int (*int2int)(int);
typedef int2int (*bool2_int2int)(bool);
bool2_int2int foo;
foo = baz;
}
EDIT 2: The compiler, of course, was right. The problem with my original code, as many pointed out, is that foo
in main()
is a declaration of a function, and not a function pointer. The error in the assignment was therefore not conflicting types but assigning to a function, which is not possible. The correct code is:
#include <stdlib.h>
int inc(int i) { return i+1; } // int→int, like abs()
// baz is bool→(int→int)
int (*baz(bool b))(int) { return b ? &abs : &inc; }
int main() {
int (*(*foo)(bool))(int); // foo is &(bool→(int→int))
foo = &baz;
}
Upvotes: 4
Views: 6479
Reputation: 146043
#include <stdlib.h>
#include <stdbool.h>
int inc(int i) { return i+1; } // int→int, like abs()
// baz is bool→(int→int)
int (*baz(bool b))(int) { return b ? &abs : &inc; }
int main() {
int (*(*foo)(bool))(int); // foo is &(bool→(int→int))
foo = baz;
return 0;
}
So there were a few side-issues clouding the core issue. Your "bool" was being interpreted as a default-int
untyped parameter because the actual built-in is _Bool, humanized by the previously-missing #include <stdbool.h>
. The lack of a pointer declaration for the object on the stack was confounding its ability to conform to the type of the real function object in static memory just above.
Once I included <stdbool.h>
, the error shifted to "lvalue required" complaint, because there was only a function declaration and not a pointer object. The code above will compile with no warnings or errors.
Upvotes: 0
Reputation: 16256
you cannot assign to function type (int (*foo(bool))(int);
), you need to use pointer to function
int (*(*foo)(bool))(int);
foo = &baz;
Upvotes: 0
Reputation: 17114
It's difficult to be sure, but I think this is closer to the OP's intent:
// baz is a function returning a pointer to a function
int (*baz(bool b))(int) { return b ? &abs : &inc; }
int main() {
// foo is a pointer to a function
int (*foo)(int) ;
foo = baz(true); // Now foo is equal to &abs
}
Upvotes: 0
Reputation: 791779
This is a function declaration.
int (*foo(bool))(int);
If you wanted to declare a function pointer, you should do:
int (*(*foo)(bool))(int);
Upvotes: 3
Reputation: 4274
The code is in fact wrong. The problem is that this line:
int (*foo(bool))(int); // foo is &(bool→(int→int))
... doesn't mean what you think it means. It's interpreted as a declaration of a function named "foo". That makes perfect sense. Think about it - if you had wanted to forward declare "baz", you would have put int (*baz(bool))(int);
, right? Also, since baz is a function which returns a function pointer, and foo is a pointer to a function which returns a function pointer, wouldn't you expect the syntax to be more complicated?
You declared foo as a function of the same type as baz, rather than as a pointer to a function of same type as baz.
From your compiler, the first error message is the useful one - it tells you assignment of function
, i.e. you have tried to assign to a function, which is an error.
I'm not even going to try to write the correct solution without typedefs :-) Here's some code which compiles and I think is right, using typedefs:
#include <stdlib.h>
#include <stdbool.h>
typedef int(*IntReturnsInt)(int);
int inc(int i) { return i+1; }
IntReturnsInt baz(bool b) { return b ? &abs : &inc; }
int main() {
IntReturnsInt (*foo)(bool b);
foo = baz;
}
In this example the double-function-pointer concept is a bit clearer - IntReturnsInt
is a function pointer type and foo
is a pointer to a function which returns IntReturnsInt
... phew :-)
Upvotes: 7