Bug 12484 – Template Overloading or Pattern Matching Failure

Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-03-27T15:28:00Z
Last change time
2014-03-27T16:33:19Z
Assigned to
nobody
Creator
monkeyworks12

Comments

Comment #0 by monkeyworks12 — 2014-03-27T15:28:24Z
I'm not sure which is failing here, but this doesn't work (and I'm pretty sure it should). struct Zero {} struct Succ(a) {} alias One = Succ!Zero; struct Less {} struct Equal {} struct Greater {} struct Cmp(x: Zero, y: Zero, c: Equal) {} struct Cmp(x: Zero, y: Succ!n, n, c: Less) {} struct Cmp(x: Succ!n, y: Zero, n, c: Greater) {} void main() { assert(is(Cmp!(Zero, Zero, Equal))); //Ok assert(is(Cmp!(Zero, One, Less))); //Fails assert(is(Cmp!(One, Zero, Greater))); //Fails } The error message given in both cases is: Error: struct Cmp does not match any template declaration
Comment #1 by monkeyworks12 — 2014-03-27T15:32:25Z
And I just realized that the error is mine. The extra n parameter must go at the end or template inference can't figure it out, of course. This works: struct Cmp(x: Zero, y: Succ!n, c: Less, n) {} struct Cmp(x: Succ!n, y: Zero, c: Greater, n) {} void main() { assert(is(Cmp!(Zero, Zero, Equal))); //Ok assert(is(Cmp!(Zero, One, Less))); //Ok assert(is(Cmp!(One, Zero, Greater))); //Ok }
Comment #2 by bearophile_hugs — 2014-03-27T16:33:19Z
(In reply to comment #1) > And I just realized that the error is mine. In some cases it's better to ask first in D.learn. > The extra n parameter must go at > the end or template inference can't figure it out, of course. This works: > > struct Cmp(x: Zero, y: Succ!n, c: Less, n) {} > struct Cmp(x: Succ!n, y: Zero, c: Greater, n) {} > > > void main() > { > assert(is(Cmp!(Zero, Zero, Equal))); //Ok > assert(is(Cmp!(Zero, One, Less))); //Ok > assert(is(Cmp!(One, Zero, Greater))); //Ok > } It's better to use static asserts: struct Zero {} struct Succ(a) {} alias One = Succ!Zero; struct Less {} struct Equal {} struct Greater {} enum Cmp(x: Zero, y: Zero, c: Equal) = true; enum Cmp(x: Zero, y: Succ!n, c: Less, n) = true; enum Cmp(x: Succ!n, y: Zero, c: Greater, n) = true; static assert(Cmp!(Zero, Zero, Equal)); static assert(Cmp!(Zero, One, Less)); static assert(Cmp!(One, Zero, Greater)); Also take a look at the new std.traits.TemplateOf and std.traits.TemplateArgsOf (2.066). In D you can compare values with ==, types with is(x == y), and type constructors (all successive ranks) with __traits(isSame, x, y). Also take a look at the new enum/alias short syntax. An alternative implementation mixes types and values (I have had to add a new CMP): struct Zero {} struct Succ(a) {} alias One = Succ!Zero; alias Two = Succ!One; enum CMP { less, equal, greater } enum Cmp(x: Zero, y: Zero, ) = CMP.equal; enum Cmp(x: Zero, y: Succ!n, n ) = CMP.less; enum Cmp(x: Succ!n, y: Zero, n ) = CMP.greater; enum Cmp(x: Succ!n, y: Succ!m, n, m) = Cmp!(n, m); static assert(Cmp!(Zero, Zero) == CMP.equal); static assert(Cmp!(Zero, One) == CMP.less); static assert(Cmp!(One, Zero) == CMP.greater); static assert(Cmp!(One, Two) == CMP.less);