Bug 29577 - overload/SFINAE problem
Summary: overload/SFINAE problem
Status: RESOLVED DUPLICATE of bug 23055
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.0.3
: P3 minor
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2006-10-24 00:48 UTC by Michael Albert
Modified: 2009-12-08 11:21 UTC (History)
6 users (show)

See Also:
Host:
Target: powerpc-ibm-aix4.3.3.0
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 Michael Albert 2006-10-24 00:48:59 UTC
The following code reports that neither class X
nor Y contain nexted class T:

#include <iostream>
#include <vector>

struct X { typedef int T; };

class Y{ };

template<typename Z>
void foo(Z const& z,  typename Z::T* p)
{ std::cout << "has Z::T" << std::endl; }

template<typename Z>
void foo(Z const& z,  ...)
{ std::cout << "hasn't Z::T" << std::endl; }

int main(int argc, char *argv[])
{
   foo( X(), 0 );
   foo( Y(), 0 );
}

My understanding is that the ellipsis
should always have lower precedence.

Thank you.  You all do wonderful work!
Comment 1 Andrew Pinski 2006-10-24 00:56:04 UTC
This code compiles for me with 4.2.0 and 4.0.2.
As I understand this, in the Y case the first template overload gets rejected as X::T does not exist.  In the X case, the first template is an exact match so it matches that way.

Also Comeau C++ accepts the code.
Comment 2 Wolfgang Bangerth 2006-10-24 02:21:01 UTC
I'm not completely sure who's right and wrong, but here's what's happening:
the second argument in the X case is an integer (the number zero), not
an int*. Consequently, the first template is not an exact match, but
requires a cast. Gcc then takes the second template with the ellipsis
instead and produces the output
-----------------
hasn't Z::T
hasn't Z::T
-----------------
with all versions I have here (2.95...4.2pre). If you change the last
argument to (int*)0, then you get what you probably expect.

For the record, I also get this here:
-------------
g/x> icc -Xc -ansi x.cc
g/x> ./a.out 
has Z::T
hasn't Z::T
-------------

W.
Comment 3 Andrew Pinski 2006-10-24 02:30:13 UTC
Oh, I read the bug incorrectly.
As I understand it 0 is special as it is also the NULL pointer and you don't need a cast for it to assign a pointer to it.  Maybe we forget to take that into account.
Comment 4 Wolfgang Bangerth 2006-11-01 22:57:33 UTC
You don't need a cast when converting to pointer, but the data
type of "0" is still int. When determining the type of a template
parameter, it therefore tries to to make the template parameter 'int'.
Comment 5 Jonathan Wakely 2009-12-08 11:21:04 UTC
'typename X::T*' is a non-deduced context, so should not be involved in argument deduction, and 0 is a valid null pointer constant


*** This bug has been marked as a duplicate of 23055 ***