www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Template specialization ordering rules

reply David Nadlinger <see klickverbot.at> writes:
Consider this template declaration: struct Foo(T : Bar!R, U = int, R) {}

As intended, it matches Foo!(Bar!float), with Bar being some other 
parametrized type and R being correctly inferred as float.

However, it doesn't seem to count as more specialized than just »struct 
Foo(T)« – for example, the following snippet produces an ambiguity error 
with the latest DMD 2 (0219a5f):

---
struct Foo(T) {}
struct Foo(T : Bar!R, U = int, R) {}
struct Bar(R) {}

Foo!(Bar!float) f;
---

Is this a bug or by design? http://digitalmars.com/d/2.0/template.html 
unfortunately just says »Determine which is more specialized is done the 
same way as the C++ partial ordering rules.«, which isn't really helpful 
if you don't have a copy of the C++ spec at hand…

David
Apr 10 2011
next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
 Consider this template declaration: struct Foo(T : Bar!R, U =3D int, R) {}
=20
 As intended, it matches Foo!(Bar!float), with Bar being some other
 parametrized type and R being correctly inferred as float.
=20
 However, it doesn't seem to count as more specialized than just =C2=BBstr=
uct
 Foo(T)=C2=AB =E2=80=93 for example, the following snippet produces an amb=
iguity error
 with the latest DMD 2 (0219a5f):
=20
 ---
 struct Foo(T) {}
 struct Foo(T : Bar!R, U =3D int, R) {}
 struct Bar(R) {}
=20
 Foo!(Bar!float) f;
 ---
=20
 Is this a bug or by design? http://digitalmars.com/d/2.0/template.html
 unfortunately just says =C2=BBDetermine which is more specialized is done=
the
 same way as the C++ partial ordering rules.=C2=AB, which isn't really hel=
pful
 if you don't have a copy of the C++ spec at hand=E2=80=A6
C++ templates don't have the concept of : in them. Template specializes in = C++=20 are only on exact type, not implicit conversion or inheritance. So, if C++= =20 disambiguation rules are used exactly, then : would have to be ignored. I think that the issue here is that Foo!(bar!float) works with _both_=20 templates. I don't remember what the exact rules are, but in my experience,= D=20 never chooses based on precedence. Things match exactly or there's an=20 ambiguity. That being the case, you would have to make the first Foo so tha= t=20 it doesn't match _anything_ which matches the second one. To do that, you'd= =20 probably have to use a template constraint - something similar to if(!is(T : Bar!R)) but you can't use quite that constraint because the first Foo has no R. So,= it=20 could be difficult to make it so that they don't match. You could play around with more basic templates such as struct Foo(T) {} struct Foo(T : int) {} and see whether they have the same problem. If they don't, then maybe you'v= e=20 actually found a bug. I don't know. Templates get to be a bit complicated w= hen=20 you have specializations. The general rule of thumb - if not absolute rule = =2D=20 is that they need to be written in such a way that they don't conflict at a= ll. =2D Jonathan M Davis
Apr 10 2011
parent David Nadlinger <see klickverbot.at> writes:
On 4/10/11 10:15 PM, Jonathan M Davis wrote:
 I think that the issue here is that Foo!(bar!float) works with _both_
 templates.[snip tldr]
No, that isn't the issue here – there are specialization rules in place for D templates as well. Actually, I should have mentioned that the sample works fine without the U parameter on the specialization: --- struct Foo(T) {} struct Foo(T : Bar!R, R) {} struct Bar(R) {} Foo!(Bar!float) f; // correctly instantiates the second one --- David
Apr 10 2011
prev sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 4/10/2011 12:32 PM, David Nadlinger wrote:
 Consider this template declaration: struct Foo(T : Bar!R, U = int, R) {}

 As intended, it matches Foo!(Bar!float), with Bar being some other parametrized
 type and R being correctly inferred as float.

 However, it doesn't seem to count as more specialized than just »struct
Foo(T)«
 – for example, the following snippet produces an ambiguity error with the
latest
 DMD 2 (0219a5f):

 ---
 struct Foo(T) {}
 struct Foo(T : Bar!R, U = int, R) {}
 struct Bar(R) {}

 Foo!(Bar!float) f;
 ---

 Is this a bug or by design? http://digitalmars.com/d/2.0/template.html
 unfortunately just says »Determine which is more specialized is done the same
 way as the C++ partial ordering rules.«, which isn't really helpful if you
don't
 have a copy of the C++ spec at hand…
It's a bug, it should select the second one. Please post to bugzilla.
Apr 10 2011
parent David Nadlinger <see klickverbot.at> writes:
On 4/10/11 11:14 PM, Walter Bright wrote:
 It's a bug, it should select the second one. Please post to bugzilla.
Done: http://d.puremagic.com/issues/show_bug.cgi?id=5830. David
Apr 10 2011