Bug 12536 - [DR 214/200] partial ordering bug
Summary: [DR 214/200] partial ordering bug
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.3.1
: P2 normal
Target Milestone: ---
Assignee: Nathan Sidwell
URL:
Keywords: wrong-code
Depends on: 19203
Blocks:
  Show dependency treegraph
 
Reported: 2003-10-08 06:54 UTC by Joerg Walter
Modified: 2005-07-23 22:49 UTC (History)
1 user (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed: 2004-05-25 14:12:56


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Joerg Walter 2003-10-08 06:54:59 UTC
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.
Comment 1 Joerg Walter 2003-10-13 07:01:09 UTC
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.
Comment 2 Nathan Sidwell 2003-10-13 08:05:11 UTC
current development head prints
foo<R,A>
bar<R,A>
Comment 3 Joerg Walter 2003-10-13 08:15:36 UTC
Which is the same as GCC 3.3.1 does and still wrong IMHO.
Comment 4 Nathan Sidwell 2003-10-13 16:51:57 UTC
sorry I misread the example
Comment 5 Joerg Walter 2003-10-15 08:26:37 UTC
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).
Comment 6 Wolfgang Bangerth 2003-10-30 23:22:59 UTC
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.
Comment 7 Nathan Sidwell 2003-10-31 17:25:22 UTC
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!
Comment 8 Joerg Walter 2003-11-01 09:15:40 UTC
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


Comment 9 Andrew Pinski 2005-04-07 07:06:59 UTC
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]
Comment 10 Nathan Sidwell 2005-06-02 18:10:42 UTC
Closing as invalid.  Both 4.0 and mainline implement the resolution of DR214,
and hence consider the deductions unordered.