Thread overview
[Issue 12484] New: Template Overloading or Pattern Matching Failure
March 27, 2014
https://d.puremagic.com/issues/show_bug.cgi?id=12484

           Summary: Template Overloading or Pattern Matching Failure
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: nobody@puremagic.com
        ReportedBy: monkeyworks12@hotmail.com


--- Comment #0 from monkeyworks12@hotmail.com 2014-03-27 15:28:24 PDT ---
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

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
March 27, 2014
https://d.puremagic.com/issues/show_bug.cgi?id=12484


monkeyworks12@hotmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|                            |INVALID


--- Comment #1 from monkeyworks12@hotmail.com 2014-03-27 15:32:25 PDT ---
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
}

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
March 27, 2014
https://d.puremagic.com/issues/show_bug.cgi?id=12484


bearophile_hugs@eml.cc changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bearophile_hugs@eml.cc


--- Comment #2 from bearophile_hugs@eml.cc 2014-03-27 16:33:19 PDT ---
(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);

-- 
Configure issuemail: https://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------