Bug 36486 - g++ accepts code with ambiguous overloading
Summary: g++ accepts code with ambiguous overloading
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.1.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: accepts-invalid
Depends on:
Blocks:
 
Reported: 2008-06-10 14:40 UTC by Richard Smith
Modified: 2013-05-20 18:21 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Richard Smith 2008-06-10 14:40:42 UTC
g++ (at least versions 3.3.5, 3.4.4 and 4.1.1) accepts the following code, which I think is ill-formed:


template<typename T> struct F {};

template<typename C, typename R>
int f(R (C::*f)() const, const F<R> &n = F<R>()) { return 0; } // f0

template<typename C, typename R>
int f(const R &(C::*f)() const, const F<R> &n = F<R>()) { return 1; } // f1

struct X { const X &foo() const { return *this; } };

int main() { return f(&X::foo); }


Here, g++ is presumably deciding that f1 is more specialized than f0, despite f0's arguments not being deducible from f1 (indeed, there is no pair of argument types (T1, T2) which both f0 and f1 accept).

EDG's frontend rejects the above code.
Comment 1 Richard Smith 2008-06-10 14:51:10 UTC
FWIW, Microsoft's recent compilers agree that this is ill-formed also.
Comment 2 Peter Bindels 2008-06-10 21:32:57 UTC
It's still warning free on 4.3.1 (except with all turned on, when ti complains about unused parameters but nothing else).

As far as I can tell the second template matches the subset of the matches for the first template where R would be an const ? &, with the second parameter matching a different but still default constructed type. It's not ambiguous because of the const at least.

I don't see why this would not work? Do you have an std reference for why this would be ill-formed?
Comment 3 Richard Smith 2008-06-11 12:58:26 UTC
I'm not 100% certain that g++ is at fault. Given that icc, Comeau and MS all reject it, I'm inclined to think that g++ is probably the one which gets this wrong, so I've raised this here first.

This hinges on whether f0 and f1 are ordered by the standard partial ordering on function templates. It appears superficially that they are not, since from the arguments to f1 you cannot deduce the template parameters of f0, nor vice versa. However, it appears to depend on interpretation of [temp.deduct.type]/5, which says that "The non-deduced contexts are: [...] A template parameter used in the parameter type of a function parameter that has a default argument that is being used in the call for which argument deduction is being done". I'm not sure whether that applies here, but if it does, perhaps that makes f1 more specialized than f0, and this is a bug in all the other compilers.
Comment 4 Paolo Carlini 2013-05-20 17:29:48 UTC
Current ICC and Clang accept this, like GCC. Jason, can you double check that we are already doing the right thing?
Comment 5 Richard Smith 2013-05-20 18:06:58 UTC
N3281 changed the rules such that g++ is now correct.
Comment 6 Paolo Carlini 2013-05-20 18:21:48 UTC
Ah, great, thanks!