Consider the following code:
void func(int) {}
template<typename T> void templatedFunc(T) {}
int main()
{
void (*p)(int) = func;
bool test1 = p==func;
//bool test2 = p==templatedFunc<int>; // compilation error
bool test3 = p==&templatedFunc<int>; // but this works
}
If you uncomment the test2
line and try to compile the code with g++, you'll get the following error:
test.cpp: In function ‘int main()’:
test.cpp:8:21: error: assuming cast to type ‘void (*)(int)’ from overloaded function [-fpermissive]
bool test2 = p==templatedFunc<int>; // compilation error
^~~~~~~~~~~~~~~~~~
I get this result on g++ 5.3.0 and 6.2.0. At the same time, compilation with clang++ 3.6.0 succeeds without warnings.
Which compiler is correct according to the Standard here — g++, which gives an error or clang++, which doesn't?
And if g++ is right, then why is there such an asymmetry with normal functions vs templated functions regarding the need of explicit address-of operator?
Pointers to objects or functions of the same type (after pointer conversions) can be compared for equality. Two pointers of the same type compare equal if and only if they are both null, both point to the same function, or both represent the same address (3.9. 2).
1) Unlike normal pointers, a function pointer points to code, not data. Typically a function pointer stores the start of executable code. 2) Unlike normal pointers, we do not allocate de-allocate memory using function pointers. 3) A function's name can also be used to get functions' address.
2. What will we not do with function pointers? Explanation: As it is used to execute a block of code, So we will not allocate or deallocate memory.
A pointer to a function points to the address of the executable code of the function. You can use pointers to call functions and to pass functions as arguments to other functions.
This is a gcc bug, and you are in a corner case, in the C++ standard, Address of overloaded function §13.4 ([over.over]/1):
A use of an overloaded function name without arguments is resolved in certain contexts to a function, a pointer to function or a pointer to member function for a specific function from the overload set. A function template name is considered to name a set of overloaded functions in such contexts. The function selected is the one whose type is identical to the function type of the target type required in the context. [ Note: That is, the class of which the function is a member is ignored when matching a pointer-to-member-function type. — end note ] The target can be:
(1.1) — an object or reference being initialized (8.5, 8.5.3, 8.5.4),
(1.2) — the left side of an assignment (5.18),
(1.3) — a parameter of a function (5.2.2),
(1.4) — a parameter of a user-defined operator (13.5),
(1.5) — the return value of a function, operator function, or conversion (6.6.3),
(1.6) — an explicit type conversion (5.2.3, 5.2.9, 5.4), or
(1.7) — a non-type template-parameter (14.3.2).
The overloaded function name can be preceded by the & operator. An overloaded function name shall not be used without arguments in contexts other than those listed. [ Note: Any redundant set of parentheses surrounding the overloaded function name is ignored (5.1). — end note ]
Do you see what is lacking in the list from (1.1) to (1.7)... built-in operators!
If you declare an overload of operator ==
both gcc will not complain with the comparison, more than that you do not have to explicitly specialize the template function:
void func(int) {}
template<class T>
void templatedFunc(T) {}
struct s{};
bool operator==(s, void(*)(int)){return false;}
int main()
{
void (*p)(int) = templatedFunc;
bool test1 = p==func;
bool test2 = s{} == templatedFunc<int>; // no error - no overload resolution
bool test3 = s{} == templatedFunc; // no error - overload resolution
bool test4 = p == templatedFunc<int>; // gcc error, but not an error -
// no overload resolution
//bool test5 = p == templatedFunc; // error - overload resolution not
// performed for built-int operators
}
test2
and test3
compiles with gcc. test4
does not compile on gcc, but there are no overload resolution, you explicitly specialized the function. It really should compile. test5
does not compile as stated in the standard. In this case gcc produces the exact same error message as for test4
. This is surely a gcc bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With