Hello, the following program ---------- #include <iostream> template<class T> struct some_type {}; template<typename A> some_type<A> foo(A const& a) { std::cout << "foo<A>" << std::endl; return some_type<A>(); } template<typename R, typename A> some_type<R> foo(A const& a) { std::cout << "foo<R,A>" << std::endl; return some_type<R>(); } template<typename A> some_type<A> bar(A const& a, A const& = A()) { std::cout << "bar<A>" << std::endl; return some_type<A>(); } template<typename R, typename A> some_type<R> bar(A const& a, R const& = R()) { std::cout << "bar<R,A>" << std::endl; return some_type<R>(); } int main() { foo<int>(0); bar<int>(0); } ---------- outputs ---------- foo<R,A> bar<A> ---------- when compiled with GCC 2.95.3 and ---------- foo<R,A> bar<R,A> ---------- when compiled with GCC 3.3.1. I believe GCC 2.95.3 is correct. Best, Joerg Walter P.S.: thanks to Patrick Kowalzick, Chris Theis and Graeme Prentice.
This is an old regression. GCC 3.0.1 already is broken and gives the same result as newer GCCs. EDG-based compilers like ICC 7.1 seem to agree with GCC 2.95.3.
current development head prints foo<R,A> bar<R,A>
Which is the same as GCC 3.3.1 does and still wrong IMHO.
sorry I misread the example
Due to Graeme's and Patrick's explanations I see the following reasoning to believe that the newer GCCs are wrong: 1. Overloaded foo() (i) template<typename A> some_type<A> foo(A const& a) (ii) template<typename R, typename A> some_type<R> foo(A const& a) For (i) synthesize unique type U for template parameter A. Call the function (ii) with U const& u: foo(u) For (ii) A is deduced to U and deduction of R fails. (i) can't call (ii) For (ii) synthesize unique types U1, U2 for template parameters R, A. Call the function (i) with U2 const& u2: foo(u2) For (i) A is deduced to U2. (ii) can call (i) (ii) is more specialized than (i) 2. Overloaded bar() (i) template<typename A> some_type<A> bar(A const& a, A const& = A()) (ii) template<typename R, typename A> some_type<R> bar(A const& a, R const& = R()) For (i) synthesize unique type U for template parameter A. Call the function (ii) with U const& u1, U const& u2: bar(u1, u2) For (ii) A is deduced to U and R is deduced to U. (i) can call (ii) For (ii) synthesize unique types U1, U2 for template parameters R, A. Call the function (i) with U1 const& u1, U2 const& u2: bar(u2, u1) For (i) deduction of A fails (it could be U1 or U2). (ii) can't call (i) (i) is more specialized.than (ii). Newer GCCs believe (ii) is more specialized than (i).
For what it's worth: here is what icc 7 says: g/x> ./a.out foo<R,A> bar<A> g/x> icc x.cc -Xc -ansi g/x> ./a.out foo<R,A> bar<A> The same holds for a development snapshot of icc8 I happen to have around. W.
Actually, I beleive GCC is correct, but there is a DR about this somewhere. this one, I think http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#214 and #200 which points back to 214 Here is my reasoning. 2. Overloaded bar() (i) template<typename A> some_type<A> bar(A const& a, A const& = A()) (ii) template<typename R, typename A> some_type<R> bar(A const& a, R const& = R()) [14.5.5.2]/6 tells us that the presence of unused elliopsis and default arguments have no effect on the partial ordering of function templates. GCC takes that to mean that in partial ordering we only consider the actual parameters explicitly specified. Also partial ordering does not consider any explicitly specified template arguments. what happens is that we can take (i) and deduce against (ii), ut in deducing in the other direction we cannot deduce a type for the first template parameter (R). so (ii) is more specialized than (i). #214 will allow the undeduce R, as is given an explicit arg, and is not being used for partial ordering. Doing so will make deduction work in both directions and hence make the ordering ambiguous. So all the compilers a wrong!
Subject: Re: Regression regarding partial ordering Dear Nathan, you wrote: > Actually, I beleive GCC is correct, but there is a DR about this somewhere. this > one, I think http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/cwg_active.html#214 > and #200 which points back to 214 Yes, I've noticed these defect reports (thanks to Chris Theis) and don't fully understand the relevance of their resolution for our problem. Are these resolutions already implemented in GCC? > Here is my reasoning. > 2. Overloaded bar() > > (i) template<typename A> > some_type<A> bar(A const& a, A const& = A()) > (ii) template<typename R, typename A> > some_type<R> bar(A const& a, R const& = R()) > > [14.5.5.2]/6 tells us that the presence of unused elliopsis and > default arguments have no effect on the partial ordering of > function templates. Just for the record: GCC 3.3.2 and ICC 7.1 correctly translate the example of [14.5.5.2]/6, GCC 2.95.3 is broken. > GCC takes that to mean that in > partial ordering we only consider the actual parameters explicitly > specified. Also partial ordering does not consider any explicitly > specified template arguments. > > what happens is that we can take (i) and deduce against (ii), ut > in deducing in the other direction we cannot deduce a type > for the first template parameter (R). so (ii) is more > specialized than (i). When I add template<typename A> some_type<A> baz(A const& a, A const&); template<typename R, typename A> some_type<R> bar(A const& a, R const&); to my example, all compilers agree to resolve baz<int>(0, 0); to baz<A> and I get the desired effect of controlling overload resolution (for some price). You've brought a strong argument that bar() should be handled like foo(). > #214 will allow the undeduce R, as is given an explicit arg, and is > not being used for partial ordering. Doing so will make deduction work > in both directions and hence make the ordering ambiguous. > > So all the compilers a wrong! Ouch. Thanks for your effort, Joerg
Hmm, on the mainline we reject this code: t.cc: In function 'int main()': t.cc:31: error: call of overloaded 'foo(int)' is ambiguous t.cc:7: note: candidates are: some_type<A> foo(const A&) [with A = int] t.cc:13: note: some_type<A> foo(const A&) [with R = int, A = int] t.cc:32: error: call of overloaded 'bar(int)' is ambiguous t.cc:19: note: candidates are: some_type<A> bar(const A&, const A&) [with A = int] t.cc:25: note: some_type<A> bar(const A&, const R&) [with R = int, A = int]
Closing as invalid. Both 4.0 and mainline implement the resolution of DR214, and hence consider the deductions unordered.