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);