Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Overload resolution with template and non-template functions

3 views
Skip to first unread message

Rodolfo Lima

unread,
Jul 20, 2007, 4:20:32 PM7/20/07
to
Hi, the snippet bellow compiles with Visual Studio and doesn't compile
with gcc-4.2. After some debating over gcc mailing list, we've nailed
it to a possible misinterpretation of the standard, section 13.4,
paragraph 1.

template <class T> void foo() {}
void foo() {}

template <class F> void bar(F f) {}
bar(&foo);

Visual Studio compiles fine, and the overload used is the non template
function. But gcc chokes at the "bar" call, saying:

"error: no matching function for call to 'bar(<unresolved overloaded
function type>)'"

According to the standard, an overload resolution attempt should be
done if and only if it's one of the 7 cases outlined there. One of the
cases is when the target of the address expression is a function's
argument (case 3).

Visual Studio seems to match the call above to case 3, but GCC
doesn't, maybe because the call target is a template function's
argument, not a "function's argument". Now... by saying "a parameter
of a function (5.2.2)", the case 3 includes both template and non
template functions, or just the latter?

Thanks,
Rodolfo Lima.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Greg Herlihy

unread,
Jul 21, 2007, 11:49:19 PM7/21/07
to
On Jul 20, 1:20 pm, Rodolfo Lima <rodl...@gmail.com> wrote:
> Hi, the snippet bellow compiles with Visual Studio and doesn't compile
> with gcc-4.2. After some debating over gcc mailing list, we've nailed
> it to a possible misinterpretation of the standard, section 13.4,
> paragraph 1.
>
> template <class T> void foo() {}
> void foo() {}
>
> template <class F> void bar(F f) {}
> bar(&foo);
>
> Visual Studio compiles fine, and the overload used is the non template
> function. But gcc chokes at the "bar" call, saying:
>
> "error: no matching function for call to 'bar(<unresolved overloaded
> function type>)'"
>
> According to the standard, an overload resolution attempt should be
> done if and only if it's one of the 7 cases outlined there. One of the
> cases is when the target of the address expression is a function's
> argument (case 3).

No, case 3 states that the target must a function parameter type - not
a function argument type. And in order for bar() to have a function
parameter whose type could be matched - bar() must first be
instantiated (or "specialized"). Now, instantiating bar() in this
particular case, first requires deducing "&foo"'s type. And since
deducing a template type parameter from the address of an overloaded
function name does not lead to overload resolution (in other words, it
is not one of the seven cases listed in '13.4), the use of "&foo" in
this context is ill-formed. So gcc is correct.

Note that explicitly specializing bar() would provide a function
parameter type that can be matched with "&foo". For example:

template <class T> void foo() {}
void foo() {}

template <class F> void bar(F f) {}

int main()
{
bar<void(*)()>(&foo); // OK
}

Explicitly specializing the function template bar() means that the
call to bar() now has a function parameter type to serve as a target
for "&foo". So in this case, overload resolution does take place - it
succeeds - and the program is well-formed.

> Visual Studio seems to match the call above to case 3, but GCC
> doesn't, maybe because the call target is a template function's
> argument, not a "function's argument". Now... by saying "a parameter
> of a function (5.2.2)", the case 3 includes both template and non
> template functions, or just the latter?

Case 3 applies to functions and function template specializations.
Case 3 does not apply to template type deduction - and since none of
the other six cases do either - the original program is ill-formed.

Greg

Rodolfo Lima

unread,
Jul 24, 2007, 6:58:11 PM7/24/07
to
On 22 jul, 00:49, Greg Herlihy <gre...@pacbell.net> wrote:
> No, case 3 states that the target must a function parameter type - not
> a function argument type. And in order for bar() to have a function
> parameter whose type could be matched - bar() must first be
> instantiated (or "specialized"). Now, instantiating bar() in this
> particular case, first requires deducing "&foo"'s type. And since
> deducing a template type parameter from the address of an overloaded
> function name does not lead to overload resolution (in other words, it
> is not one of the seven cases listed in '13.4), the use of "&foo" in
> this context is ill-formed. So gcc is correct.

Wouldn't be the case of eliminating from the overload set all template
functions with template arguments that cannot be deduced, leaving only
normal functions and specialized template functions? I cannot see any
bad implications in doing this, and IMO it would work as one would
expect. Was it a deliberate decision for not allowing this kind of
overload resolution, or it was a situation that the committee didn't
think of?

tinlans

unread,
Jul 25, 2007, 8:51:31 PM7/25/07
to
On 7 25 , 6 58 , Rodolfo Lima <rodl...@gmail.com> wrote:
> Wouldn't be the case of eliminating from the overload set all template
> functions with template arguments that cannot be deduced, leaving only
> normal functions and specialized template functions? I cannot see any
> bad implications in doing this, and IMO it would work as one would
> expect. Was it a deliberate decision for not allowing this kind of
> overload resolution, or it was a situation that the committee didn't
> think of?

The point is that the compiler is hard to know what specialization of
`bar<>()' should be called. The actions which are described in section
13.4 must be done after template argument deducing.

Although you have explicitly instantiated one by "template void
bar(void (*f)());",
there are still not any approaches to select it automatcially. When
the compiler
saw the line "bar(&foo);', it should to determine what specialzation
of bar<>() it
should be instantiated (and then checks if there is aleready one). It
needs to know
the type of its function argument (i.e., the type of `f'). If it
cannot know about
the type of its function argument, the template argument deducing will
be failed.
At the moment, the compiler cannot find a "matching function" for
calling to it.
So you got the error message: "no matching function for call to ...".

Hmm...
In practice, it's reasonable to search all specializations and
ordinary functions
and select the ordinary one if there is only one ordinary function.
Perhaps it's the
approach what MSVC and Comeau C++ Compiler adopted (They can compile
your example
without any problems). But the C++ standard didn't force them to do
it. Maybe we
lost some traps the committee has already concerned. I'm also curious
about it.

Greg Herlihy

unread,
Jul 26, 2007, 10:59:28 AM7/26/07
to


On 7/24/07 3:58 PM, in article
1185312168.3...@19g2000hsx.googlegroups.com, "Rodolfo Lima"
<rod...@gmail.com> wrote:

> On 22 jul, 00:49, Greg Herlihy <gre...@pacbell.net> wrote:
>> No, case 3 states that the target must a function parameter type - not
>> a function argument type. And in order for bar() to have a function
>> parameter whose type could be matched - bar() must first be
>> instantiated (or "specialized"). Now, instantiating bar() in this
>> particular case, first requires deducing "&foo"'s type. And since
>> deducing a template type parameter from the address of an overloaded
>> function name does not lead to overload resolution (in other words, it
>> is not one of the seven cases listed in '13.4), the use of "&foo" in
>> this context is ill-formed. So gcc is correct.
>
> Wouldn't be the case of eliminating from the overload set all template
> functions with template arguments that cannot be deduced, leaving only
> normal functions and specialized template functions? I cannot see any
> bad implications in doing this, and IMO it would work as one would
> expect. Was it a deliberate decision for not allowing this kind of
> overload resolution, or it was a situation that the committee didn't
> think of?

I think my earlier response failed to consider the possibility that type
deduction alone may be enough to resolve "&foo's" type when passed as
function pointer argument. And in fact §14.8.2.2 seems to confirm as much.
So although I was technically correct that no overload resolution takes
place in this situation, I was incorrect in thinking that overload
resolution was the only way to match &foo to a function pointer type.

So I now think gcc should accept the original program as valid.

Greg

0 new messages