Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
March 02, 2018 template auto value | ||||
---|---|---|---|---|
| ||||
I believe I found small hole in template parameter semantics. I've summarized it here (https://github.com/marler8997/dlangfeatures#template-auto-value-parameter). Wanted to get feedback before I look into creating a PR for it. ---------------------------------- COPY/PASTED from https://github.com/marler8997/dlangfeatures#template-auto-value-parameter ---------------------------------- If you reference the D grammar for templates (See https://dlang.org/spec/template.html), there are currently 5 categories of template parameters: TemplateParameter: TemplateTypeParameter TemplateValueParameter TemplateAliasParameter TemplateSequenceParameter TemplateThisParameter However there is a hole in this list, namely, generic template value parameters. The current TemplateValueParameter grammar node must explicitly declare a "BasicType": TemplateValueParameter: BasicType Declarator BasicType Declarator TemplateValueParameterSpecialization BasicType Declarator TemplateValueParameterDefault BasicType Declarator TemplateValueParameterSpecialization TemplateValueParameterDefault For example: --- template foo(string value) { } foo!"hello"; --- However, you can't create a template that accepts a value of any type. This would a good use case for the auto keyword, i.e. --- template foo(auto value) { } foo!0; foo!"hello"; --- This would be a simple change to the grammar, namely, BasicTemplateType: BasicType auto TemplateValueParameter: BasicTemplateType Declarator BasicTemplateType Declarator TemplateValueParameterSpecialization BasicTemplateType Declarator TemplateValueParameterDefault BasicTemplateType Declarator TemplateValueParameterSpecialization TemplateValueParameterDefault |
March 02, 2018 Re: template auto value | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan Marler | On Fri, Mar 02, 2018 at 11:51:08PM +0000, Jonathan Marler via Digitalmars-d wrote: > I believe I found small hole in template parameter semantics. [...] you can't create a template that accepts a value of any type. Not true: template counterexample(alias T) {} int x; string s; alias U = counterexample!x; // OK alias V = counterexample!1; // OK alias W = counterexample!"yup"; // OK alias X = counterexample!s; // OK alias Z = counterexample!int; // NG The last one fails because a value is expected, not a type. If you *really* want to accept both values and types, `...` comes to the rescue: template rescue(T...) if (T.length == 1) {} int x; string s; alias U = rescue!x; // OK alias V = rescue!1; // OK alias W = rescue!"yup"; // OK alias X = rescue!s; // OK alias Z = rescue!int; // OK! T -- In a world without fences, who needs Windows and Gates? -- Christian Surchi |
March 03, 2018 Re: template auto value | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On 03.03.2018 01:20, H. S. Teoh wrote:
> On Fri, Mar 02, 2018 at 11:51:08PM +0000, Jonathan Marler via Digitalmars-d wrote:
>> I believe I found small hole in template parameter semantics.
>> [...] you can't create a template that accepts a value of any type.
> Not true:
>
> template counterexample(alias T) {}
>
> int x;
> string s;
> alias U = counterexample!x; // OK
> alias V = counterexample!1; // OK
> alias W = counterexample!"yup"; // OK
> alias X = counterexample!s; // OK
>
> alias Z = counterexample!int; // NG
>
> The last one fails because a value is expected, not a type.
No, it fails because a "symbol" is expected, not a basic type. There really is no good reason why int should not be accepted -- a class or struct type would be accepted. IIRC Walter has agreed to this, and it's just pending implementation.
|
March 03, 2018 Re: template auto value | ||||
---|---|---|---|---|
| ||||
Posted in reply to H. S. Teoh | On Saturday, 3 March 2018 at 00:20:14 UTC, H. S. Teoh wrote:
> On Fri, Mar 02, 2018 at 11:51:08PM +0000, Jonathan Marler via Digitalmars-d wrote:
>> [...]
>
> Not true:
>
> template counterexample(alias T) {}
>
> int x;
> string s;
> alias U = counterexample!x; // OK
> alias V = counterexample!1; // OK
> alias W = counterexample!"yup"; // OK
> alias X = counterexample!s; // OK
>
> alias Z = counterexample!int; // NG
>
> The last one fails because a value is expected, not a type.
>
> If you *really* want to accept both values and types, `...` comes to the rescue:
>
> template rescue(T...) if (T.length == 1) {}
>
> int x;
> string s;
> alias U = rescue!x; // OK
> alias V = rescue!1; // OK
> alias W = rescue!"yup"; // OK
> alias X = rescue!s; // OK
> alias Z = rescue!int; // OK!
>
>
> T
Ah thank you...I guess I didn't realize that literals like 1 and "yup" were considered "symbols" when it comes to alias template parameters.
|
March 05, 2018 Re: template auto value | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan Marler | On 3/2/18 8:49 PM, Jonathan Marler wrote:
> On Saturday, 3 March 2018 at 00:20:14 UTC, H. S. Teoh wrote:
>> On Fri, Mar 02, 2018 at 11:51:08PM +0000, Jonathan Marler via Digitalmars-d wrote:
>>> [...]
>>
>> Not true:
>>
>> template counterexample(alias T) {}
>>
>> int x;
>> string s;
>> alias U = counterexample!x; // OK
>> alias V = counterexample!1; // OK
>> alias W = counterexample!"yup"; // OK
>> alias X = counterexample!s; // OK
>>
>> alias Z = counterexample!int; // NG
>>
>> The last one fails because a value is expected, not a type.
>>
>> If you *really* want to accept both values and types, `...` comes to the rescue:
>>
>> template rescue(T...) if (T.length == 1) {}
>>
>> int x;
>> string s;
>> alias U = rescue!x; // OK
>> alias V = rescue!1; // OK
>> alias W = rescue!"yup"; // OK
>> alias X = rescue!s; // OK
>> alias Z = rescue!int; // OK!
>>
>>
>> T
>
> Ah thank you...I guess I didn't realize that literals like 1 and "yup" were considered "symbols" when it comes to alias template parameters.
Well, they aren't. But template alias is a bit of a mess when it comes to the spec. It will accept anything except keywords AFAIK. Would be nice if it just worked like the variadic version.
The variadic version is what is usually needed (you see a lot of if(T.length == 1) in std.traits).
But, if you wanted to ensure values (which is more akin to your proposal), you can do:
template rescue(alias val) if(!is(val)) // not a type
-Steve
|
March 05, 2018 Re: template auto value | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Monday, 5 March 2018 at 13:03:50 UTC, Steven Schveighoffer wrote: > On 3/2/18 8:49 PM, Jonathan Marler wrote: >> On Saturday, 3 March 2018 at 00:20:14 UTC, H. S. Teoh wrote: >>> On Fri, Mar 02, 2018 at 11:51:08PM +0000, Jonathan Marler via Digitalmars-d wrote: >>>> [...] >>> >>> Not true: >>> >>> template counterexample(alias T) {} >>> >>> int x; >>> string s; >>> alias U = counterexample!x; // OK >>> alias V = counterexample!1; // OK >>> alias W = counterexample!"yup"; // OK >>> alias X = counterexample!s; // OK >>> >>> alias Z = counterexample!int; // NG >>> >>> The last one fails because a value is expected, not a type. >>> >>> If you *really* want to accept both values and types, `...` comes to the rescue: >>> >>> template rescue(T...) if (T.length == 1) {} >>> >>> int x; >>> string s; >>> alias U = rescue!x; // OK >>> alias V = rescue!1; // OK >>> alias W = rescue!"yup"; // OK >>> alias X = rescue!s; // OK >>> alias Z = rescue!int; // OK! >>> >>> >>> T >> >> Ah thank you...I guess I didn't realize that literals like 1 and "yup" were considered "symbols" when it comes to alias template parameters. > > Well, they aren't. But template alias is a bit of a mess when it comes to the spec. It will accept anything except keywords AFAIK. Would be nice if it just worked like the variadic version. > > The variadic version is what is usually needed (you see a lot of if(T.length == 1) in std.traits). > > But, if you wanted to ensure values (which is more akin to your proposal), you can do: > > template rescue(alias val) if(!is(val)) // not a type > > -Steve Thanks for the tip, it looks like the spec does mention "literals" but "alias" parameters are even more versatile than that (https://dlang.org/spec/template.html#TemplateAliasParameter). For example you can pass a function call. I've created an issue to make sure we update the spec to reflect the true capabilities: https://issues.dlang.org/show_bug.cgi?id=18558 |
Copyright © 1999-2021 by the D Language Foundation