Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding how the compiler resolves pointer to functions

The following code snippet:

#include <iostream>

void does() { std::cout << "do" << std::endl; }
void does(bool b = false) { std::cout << "do(bool)" << std::endl; }

void fwd(void (*func)(bool))
{
    func(false);
}

int main(int, char**)
{
    fwd(&does);
    fwd(does);
    fwd(*does);
}

understandably produces the following error:

test.cpp:15:10: error: overloaded function with no contextual type information

The compiler cannot discern which of the functions I intend to use. What I don't understand is why the code will correctly run when I comment out the line that reads:

fwd(*does)

Why can the compiler suddenly resolve the ambiguousness?

int main(int, char**)
{
    fwd(&does);
    fwd(does);
}

Also, without overloading does the snippet will correctly run with all 3 calls. This snippet runs fine...

#include <iostream>

void does(bool b = false) { std::cout << "do(bool)" << std::endl; }

void fwd(void (*func)(bool))
{
    func(false);
}

int main(int, char**)
{
    fwd(&does);
    fwd(does);
    fwd(*does);
}

I'm compiling this with gcc 4.6.3 on a Linux box.

Thanks for the help!

like image 206
JDR Avatar asked Nov 07 '14 01:11

JDR


1 Answers

The answer to your question is in the overload-resolution rules for functions.
Specifically, there is an exception for using & before the function-name (once) not breaking overload-resolution, but none for using *.
Also see that only one of those two functions accept that single argument:

13.4 Address of overloaded function [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

  • an object or reference being initialized (8.5, 8.5.3),
  • the left side of an assignment (5.17),
  • a parameter of a function (5.2.2),
  • a parameter of a user-defined operator (13.5),
  • the return value of a function, operator function, or conversion (6.6.3),
  • an explicit type conversion (5.2.3, 5.2.9, 5.4), or
  • 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.

Quote is from n3242 (c++11), with bold by me.

like image 56
Deduplicator Avatar answered Oct 24 '22 00:10

Deduplicator