This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/47227] New: GCC ignores conversion function template specializatons if a derived class' conversion function converts to the same type
- From: "schaub.johannes at googlemail dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: Sat, 8 Jan 2011 22:59:14 +0000
- Subject: [Bug c++/47227] New: GCC ignores conversion function template specializatons if a derived class' conversion function converts to the same type
- Auto-submitted: auto-generated
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=47227
Summary: GCC ignores conversion function template
specializatons if a derived class' conversion function
converts to the same type
Product: gcc
Version: 4.6.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
AssignedTo: unassigned@gcc.gnu.org
ReportedBy: schaub.johannes@googlemail.com
Unless I'm missing something, the following is ambiguous:
template<typename T1, typename T2>
struct A { };
struct base {
template<typename T2, typename T1>
operator A<T1, T2>();
};
struct derived : base {
template<typename T1, typename T2>
operator A<T1, T2>();
};
int main() {
derived().operator A<int, int>();
}
However, GCC always wants to take the derived class version.
The reason for ambiguity is:
A<param-#1#1, param-#1#2> is another type than A<param-#1#2, param-#1#1> (prior
to deduction. When collecting candidates, 14.5.2/6 says:
"A specialization of a conversion function template is not found by name
lookup. Instead, any conversion function templates visible in the context of
the use are considered. For each such operator, if argument deduction
succeeds
(14.8.2.3), the resulting specialization is used as if found by name lookup."
In the context of the use, both functions templates are visible, so both are
sent to argument deduction. Deduction will succeed, so *the specialization is
used as if found by name lookup*. Name lookup cannot find declarations that are
hidden, so this quite clearly requires the above to be ambiguous, and doesn't
allow the base-class version to be "filtered out" later on. Hiding only takes
place prior to deduction:
template<typename T1, typename T2>
struct A { };
struct base {
template<typename T1, typename T2>
operator A<T1, T2>();
};
struct derived : base {
template<typename T1, typename T2>
operator A<T1, T2>();
};
int main() {
derived().operator A<int, int>();
}
Now that is not ambiguous anymore, and will call the derived class version,
because in the context of the use, the base-class version is hidden (12.3/5 and
3/8).
Note that by constructing cases making the base-class version more specialized
than the derived class version, we could actually make this a rejects-valid
bug:
template<typename T1, typename T2>
struct A { };
struct base {
template<typename T1, typename T2>
operator A<T1*, T2>();
};
struct derived : base {
private:
template<typename T1, typename T2>
operator A<T1, T2>();
};
int main() {
derived().operator A<int*, int>();
}
Comeau accepts this one just fine, while GCC rejects it, thinking the
base-version is hidden.