www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Template argument deduction fails with alias

reply Ben Jones <fake fake.fake> writes:
I have an alias that looks like

static if(...){
   alias AliasType = SumType!(...);
}

which I use in a template constraint for a function template:

bool func(T: AliasType!Args, Args...)(T t){ ... }


When I try to call func with an AliasType object, the argument 
deduction fails with a message saying that the argument type (a 
SumType) doesn't match the template constraint (an AliasType)

Things do work if I change the template constraint to be a 
SumType rather an an AliasType

Is there a workaround to this?  Here's a complete example: 
https://run.dlang.io/is/buRGTs
Aug 31 2020
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 8/31/20 9:11 PM, Ben Jones wrote:
 I have an alias that looks like
 
 static if(...){
    alias AliasType = SumType!(...);
 }
 
 which I use in a template constraint for a function template:
 
 bool func(T: AliasType!Args, Args...)(T t){ ... }
 
 
 When I try to call func with an AliasType object, the argument deduction 
 fails with a message saying that the argument type (a SumType) doesn't 
 match the template constraint (an AliasType)
 
 Things do work if I change the template constraint to be a SumType 
 rather an an AliasType
 
 Is there a workaround to this?  Here's a complete example: 
 https://run.dlang.io/is/buRGTs
 
Very old enhancement request (I doubt this will ever happen): https://issues.dlang.org/show_bug.cgi?id=1807 -Steve
Aug 31 2020
prev sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Tuesday, 1 September 2020 at 01:11:35 UTC, Ben Jones wrote:
 I have an alias that looks like

 static if(...){
   alias AliasType = SumType!(...);
 }

 which I use in a template constraint for a function template:

 bool func(T: AliasType!Args, Args...)(T t){ ... }


 When I try to call func with an AliasType object, the argument 
 deduction fails with a message saying that the argument type (a 
 SumType) doesn't match the template constraint (an AliasType)

 Things do work if I change the template constraint to be a 
 SumType rather an an AliasType

 Is there a workaround to this?  Here's a complete example: 
 https://run.dlang.io/is/buRGTs
This is a very old known bug: https://issues.dlang.org/show_bug.cgi?id=1807 Attempts have been made to fix it, but the problem is a lot more complicated than it looks at first glance, so I wouldn't expect a solution any time soon. Aside from using SumType directly in the function signature, another workaround is to use a wrapper struct instead of an alias: struct AliasType(Args...) { SumType!Args data; alias data this; } bool func(T : AliasType!Args, Args...)(T t) { ... }
Aug 31 2020
parent reply Ben Jones <fake fake.fake> writes:
On Tuesday, 1 September 2020 at 01:26:30 UTC, Paul Backus wrote:

 Aside from using SumType directly in the function signature, 
 another workaround is to use a wrapper struct instead of an 
 alias:

     struct AliasType(Args...) {
         SumType!Args data;
         alias data this;
     }

     bool func(T : AliasType!Args, Args...)(T t) { ... }
Thanks all. I tried using alias this at first and then I get errors trying to construct AliasType objects: auto pi = Payload!int(5); auto pe = ParseError("error"); alias PRType = ParseResult!(Payload!int, ParseError); auto pr = PRType(pi); gives: cannot implicitly convert expression `pi` of type `Payload!int` to `SumType!(Payload!int, ParseError)`
Aug 31 2020
parent Paul Backus <snarwin gmail.com> writes:
On Tuesday, 1 September 2020 at 02:48:08 UTC, Ben Jones wrote:
 Thanks all.

 I tried using alias this at first and then I get errors trying 
 to construct AliasType objects:


 auto pi = Payload!int(5);
 auto pe = ParseError("error");
 alias PRType = ParseResult!(Payload!int, ParseError);
 auto pr = PRType(pi);

 gives:

 cannot implicitly convert expression `pi` of type `Payload!int` 
 to `SumType!(Payload!int, ParseError)`
Unfortunately, `alias this` does not apply to constructors. You can either add your own constructor to the wrapper struct: struct ParseResult(Ts...) { SumType!Ts data; alias data this; this(T)(T t) if (staticIndexOf!(T, data.Types) >= 0) { data = t; } } ...or use a factory function like the following: PRType parseResult(T)(T t) { return PRType(SumType!(Payload!int, ParseError)(t)); }
Sep 01 2020