Topic: Partial ordering and non-deduced arguments


Author: rani_sharoni@hotmail.com ("Rani Sharoni")
Date: Mon, 5 Jan 2004 18:50:55 +0000 (UTC)
Raw View
Consider the following code:
template<typename T> struct A {};

template<typename T> char* f(T, char*);        // #1
template<typename T> long* f(A<T>, long*); // #2

long* p = f(A<int>(), 0); // #3

My intuition and all the compilers that I tried say that #3 is ambiguous yet
I didn't find the exact standard wording that support this.

It is obvious that both specializations have the same rank and therefore
overloading asks partial ordering to decide. Partial ordering seems to
ignore the non deduced parts of the functions and therefore the question now
is whether the resulting specializations can be falsely blamed of being
ordered?

I must be missing something.

Thanks,
Rani


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: daniel.frey@aixigo.de (Daniel Frey)
Date: Tue, 6 Jan 2004 15:35:34 +0000 (UTC)
Raw View
Rani Sharoni wrote:
> Consider the following code:
> template<typename T> struct A {};
>=20
> template<typename T> char* f(T, char*);        // #1
> template<typename T> long* f(A<T>, long*); // #2
>=20
> long* p =3D f(A<int>(), 0); // #3
>=20
> My intuition and all the compilers that I tried say that #3 is ambiguou=
s yet
> I didn't find the exact standard wording that support this.

14.5.5.2, especially /4 and /5.

> It is obvious that both specializations have the same rank and therefor=
e
> overloading asks partial ordering to decide. Partial ordering seems to
> ignore the non deduced parts of the functions and therefore the questio=
n now
> is whether the resulting specializations can be falsely blamed of being
> ordered?

I don't think so. I had a similar question from a friend some time ago=20
where he wanted to "specialize" a function for vector<T>, but although I=20
understand why people think that A<T> is more specialized than T, this=20
is just something we all have to learn at one point or another that C++=20
doesn't work this way. As it doesn't actually compile, I don't see a=20
problem here as it is at least safe and doesn't cause silent bugs.

The solution if you really want to specialize your function for A<T> -=20
as I am sure you already know, but others here might not - is writing a=20
type-trait for A and apply SFINAE.

template<typename T>
typename disable_if<is_A<T>, char*>::type
f(T, char*);

template<typename T>
typename enable_if<is_A<T>, long*>::type
f(T, long*);

Regards, Daniel

--=20
Daniel Frey

aixigo AG - financial solutions & technology
Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: rani_sharoni@hotmail.com ("Rani Sharoni")
Date: Tue, 6 Jan 2004 16:07:35 +0000 (UTC)
Raw View
Daniel Frey wrote:
> Rani Sharoni wrote:
>> Consider the following code:
>> template<typename T> struct A {};
>>
>> template<typename T> char* f(T, char*);        // #1
>> template<typename T> long* f(A<T>, long*); // #2
>>
>> long* p = f(A<int>(), 0); // #3
>>
>> My intuition and all the compilers that I tried say that #3 is
>> ambiguous yet I didn't find the exact standard wording that support
>> this.
>
> 14.5.5.2, especially /4 and /5.

I read 14.5.5.2 several times and I didn't find /4 very clear about this
issue:
[...] The transformed template is at least as specialized as the other if,
and only if, the deduction succeeds and the *deduced parameter types* are an
exact match.

I wonder if the deduced parameter types include the non deduced parts.
It seems that compilers also have some problem with about this section:

template<typename T> struct A { typedef T type; };

template<typename T> char* f2(T, typename A<T>::type);   // #1
template<typename T> long* f2(T*, typename A<T>::type*); // #2

int* arg = 0;
long* p2 = f2(arg, 0); // #3

EDG found the code well formed
GCC found #1 better and rejected the code
VC found ambiguity

They all disagree.

Rani


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: daniel.frey@aixigo.de (Daniel Frey)
Date: Tue, 6 Jan 2004 17:18:06 +0000 (UTC)
Raw View
Rani Sharoni wrote:
> Daniel Frey wrote:
>=20
>>Rani Sharoni wrote:
>>
>>>Consider the following code:
>>>template<typename T> struct A {};
>>>
>>>template<typename T> char* f(T, char*);        // #1
>>>template<typename T> long* f(A<T>, long*); // #2
>>>
>>>long* p =3D f(A<int>(), 0); // #3
>>>
>>>My intuition and all the compilers that I tried say that #3 is
>>>ambiguous yet I didn't find the exact standard wording that support
>>>this.
>>
>>14.5.5.2, especially /4 and /5.
>=20
> I read 14.5.5.2 several times and I didn't find /4 very clear about thi=
s
> issue:
> [...] The transformed template is at least as specialized as the other =
if,
> and only if, the deduction succeeds and the *deduced parameter types* a=
re an
> exact match.

Well, I also stumbled across the wording as /4 alone doesn't tell you=20
anything. It only makes sense with /5, so it would probably be better to=20
remove /5 and add the sentence to /4 directly? The "deduced parameter=20
types" you highlighted IMO are not relevant here, they just disallow=20
conversions to be used, e.g. if T is a class which has an operator=20
A<int>(). I think the "at least as specialized as" is what is confusing,=20
especially given that /5 is separated from /4 and each one on it's own=20
is incomplete.

> I wonder if the deduced parameter types include the non deduced parts.
> It seems that compilers also have some problem with about this section:
>=20
> template<typename T> struct A { typedef T type; };
>=20
> template<typename T> char* f2(T, typename A<T>::type);   // #1
> template<typename T> long* f2(T*, typename A<T>::type*); // #2
>=20
> int* arg =3D 0;
> long* p2 =3D f2(arg, 0); // #3
>=20
> EDG found the code well formed
> GCC found #1 better and rejected the code
> VC found ambiguity

Maybe EDG sees this as a partial specialization instead of an overload?=20
This would IMHO explain the behaviour, as an overload should lead to=20
ambiguity. Have you tried:

template<typename T> long* f2<T*>(T*, typename A<T>::type*); // #2

If this is the case, the question is whether the EDG is free to=20
implicitly assume a partial specialization instead of an overload. I=20
tend to say no, but I'm not sure.

Also, which GCC-version where you using? What was the output?

Regards, Daniel

--=20
Daniel Frey

aixigo AG - financial solutions & technology
Schlo=DF-Rahe-Stra=DFe 15, 52072 Aachen, Germany
fon: +49 (0)241 936737-42, fax: +49 (0)241 936737-99
eMail: daniel.frey@aixigo.de, web: http://www.aixigo.de

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]