Thread overview | ||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
February 24, 2018 Template Constraints | ||||
---|---|---|---|---|
| ||||
I am having trouble finding many useful explanations of using template constraints beyond basic usage. I would like to have a template constrant to enforce that a type can be explicitly cast to another type: void (T)(T t) if (cast(int) T)//force `cast(int) T` to be possible { // Yay I know `t` can be cast to an `int`! } Is this possible? |
February 24, 2018 Re: Template Constraints | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan | On Saturday, 24 February 2018 at 02:54:13 UTC, Jonathan wrote: > I am having trouble finding many useful explanations of using template constraints beyond basic usage. The constraint is just like static if as to what it allows inside, so you can check almost anything in there. Like for the cast, you might do void name(T)(T t) if(__traits(compiles, cast(int) t) {} just seeing it the cast compiles. You might also do if(is(T : int)) which asks if T is implicitly convertible to int. But since you want explicit cast, the compiles is prolly the way to go. is: https://dlang.org/spec/expression.html#IsExpression compiles: https://dlang.org/spec/traits.html#compiles |
February 24, 2018 Re: Template Constraints | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan | On Saturday, 24 February 2018 at 02:54:13 UTC, Jonathan wrote: > I am having trouble finding many useful explanations of using template constraints beyond basic usage. > > I would like to have a template constrant to enforce that a type can be explicitly cast to another type: > > void (T)(T t) > if (cast(int) T)//force `cast(int) T` to be possible > { > // Yay I know `t` can be cast to an `int`! > } > > Is this possible? I would have thought contracts would be ideal here? https://dlang.org/spec/contracts.html |
February 23, 2018 Re: Template Constraints | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan | On Saturday, February 24, 2018 02:54:13 Jonathan via Digitalmars-d-learn wrote:
> I am having trouble finding many useful explanations of using template constraints beyond basic usage.
>
> I would like to have a template constrant to enforce that a type can be explicitly cast to another type:
>
> void (T)(T t)
> if (cast(int) T)//force `cast(int) T` to be possible
> {
> // Yay I know `t` can be cast to an `int`!
> }
>
> Is this possible?
Well, template constraints in general usually either test that the type of one expression matches another or that a particular piece of code compiles. So, you'd need to test that the cast compiles. That requires either an is expression or __traits(compiles, ...) (or an eponymous template that contains such an expression). In this case, you could probably just do
if(is(typeof(cast(int)t)))
since as long as the result of the expression isn't void, the is expression will be true.
And note that the expression uses t, not T. You can't cast the type itself. You have to cast a value of that type.
- Jonathan M Davis
|
February 23, 2018 Re: Template Constraints | ||||
---|---|---|---|---|
| ||||
Posted in reply to psychoticRabbit | On Saturday, February 24, 2018 03:04:53 psychoticRabbit via Digitalmars-d- learn wrote:
> On Saturday, 24 February 2018 at 02:54:13 UTC, Jonathan wrote:
> > I am having trouble finding many useful explanations of using template constraints beyond basic usage.
> >
> > I would like to have a template constrant to enforce that a
> >
> > type can be explicitly cast to another type:
> > void (T)(T t)
> >
> > if (cast(int) T)//force `cast(int) T` to be possible
> >
> > {
> >
> > // Yay I know `t` can be cast to an `int`!
> >
> > }
> >
> > Is this possible?
>
> I would have thought contracts would be ideal here?
>
> https://dlang.org/spec/contracts.html
Contracts are used to assert runtime state, whereas template constraints control which arguments can be used with the template (including being used for function overloading).
The OP wants his function template to reject any arguments that can't be explicitly cast to int, whereas an in contract would be used for something like verifying at runtime that the argument was within a particular range of values.
- Jonathan M Davis
|
February 24, 2018 Re: Template Constraints | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan | On Saturday, 24 February 2018 at 02:54:13 UTC, Jonathan wrote:
> I am having trouble finding many useful explanations of using template constraints beyond basic usage.
>
> I would like to have a template constrant to enforce that a type can be explicitly cast to another type:
>
> void (T)(T t)
> if (cast(int) T)//force `cast(int) T` to be possible
> {
> // Yay I know `t` can be cast to an `int`!
> }
>
> Is this possible?
import std.traits : isIntegral;
void testTemplate(T)(T x) if (isIntegral!T)
{
writeln(x, " is an integral. yeah!");
}
|
February 24, 2018 Re: Template Constraints | ||||
---|---|---|---|---|
| ||||
Posted in reply to psychoticRabbit | On Saturday, 24 February 2018 at 03:30:45 UTC, psychoticRabbit wrote:
> On Saturday, 24 February 2018 at 02:54:13 UTC, Jonathan wrote:
>> I am having trouble finding many useful explanations of using template constraints beyond basic usage.
>>
>> I would like to have a template constrant to enforce that a type can be explicitly cast to another type:
>>
>> void (T)(T t)
>> if (cast(int) T)//force `cast(int) T` to be possible
>> {
>> // Yay I know `t` can be cast to an `int`!
>> }
>>
>> Is this possible?
>
> import std.traits : isIntegral;
> void testTemplate(T)(T x) if (isIntegral!T)
> {
> writeln(x, " is an integral. yeah!");
>
> }
or this is probably more suitable ;-)
(should you really be using an explicity convert anyway?)
void testTemplate2(T)(T x) if (isImplicitlyConvertible!(T, int))
{
writeln(x, " is implicitly convertible to an int. yeah!");
}
|
February 23, 2018 Re: Template Constraints | ||||
---|---|---|---|---|
| ||||
Posted in reply to psychoticRabbit | On Saturday, February 24, 2018 03:30:45 psychoticRabbit via Digitalmars-d- learn wrote:
> On Saturday, 24 February 2018 at 02:54:13 UTC, Jonathan wrote:
> > I am having trouble finding many useful explanations of using template constraints beyond basic usage.
> >
> > I would like to have a template constrant to enforce that a
> >
> > type can be explicitly cast to another type:
> > void (T)(T t)
> >
> > if (cast(int) T)//force `cast(int) T` to be possible
> >
> > {
> >
> > // Yay I know `t` can be cast to an `int`!
> >
> > }
> >
> > Is this possible?
>
> import std.traits : isIntegral;
> void testTemplate(T)(T x) if (isIntegral!T)
> {
> writeln(x, " is an integral. yeah!");
>
> }
That does not do what the OP requested at all. That tests whether T is one of byte, ubyte, short, ushort, int, uint, long, and ulong, whereas what the OP wants is to test whether T can be cast to int.
- Jonathan M Davis
|
February 24, 2018 Re: Template Constraints | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | On Saturday, 24 February 2018 at 03:43:25 UTC, Jonathan M Davis wrote:
> That does not do what the OP requested at all. That tests whether T is one of byte, ubyte, short, ushort, int, uint, long, and ulong, whereas what the OP wants is to test whether T can be cast to int.
>
> - Jonathan M Davis
yeah. I realised that after I had posted.
I posted a more suitable response after that though (I hope), with the intention of leading the OP away from an explicit cast, towards an implicit cast.
|
February 23, 2018 Re: Template Constraints | ||||
---|---|---|---|---|
| ||||
Posted in reply to psychoticRabbit | On Saturday, February 24, 2018 03:48:44 psychoticRabbit via Digitalmars-d- learn wrote:
> On Saturday, 24 February 2018 at 03:43:25 UTC, Jonathan M Davis
>
> wrote:
> > That does not do what the OP requested at all. That tests whether T is one of byte, ubyte, short, ushort, int, uint, long, and ulong, whereas what the OP wants is to test whether T can be cast to int.
> >
> > - Jonathan M Davis
>
> yeah. I realised that after I had posted.
>
> I posted a more suitable response after that though (I hope), with the intention of leading the OP away from an explicit cast, towards an implicit cast.
Whether an implicit cast or an explicit cast makes more sense depends entirely on what the code is doing, but either way, the conversion needs to be forced inside the function, or you end up with bugs. Far too often, when someone has a template constraint that checks an implicit conversion, the function doesn't actually force the conversion, and that can do anything from resulting in some instantiations not compiling to causing subtle bugs due to the argument being used without being converted. In general, it's actually best to avoid conversions entirely with generic code and force the caller to do the conversion if a conversion is appropriate.
But ultimately, what works best depends on what the code is trying to do.
- Jonathan M Davis
|
Copyright © 1999-2021 by the D Language Foundation