Thread overview | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
March 15, 2015 Testing implicit conversion to template instance with is() expression | ||||
---|---|---|---|---|
| ||||
Should this work? struct V(string s) { } struct S(int U) { V!"xyz" x; alias x this; } void main() { S!10 a; static assert(is(a : V!Args, Args...)); } With DMD Git master, the static assert() fails. Should it? Am I doing something wrong? How can I test whether something is implicitly convertible to any instance of a particular template? |
March 15, 2015 Re: Testing implicit conversion to template instance with is() expression | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz | On 03/15/2015 08:47 AM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm@gmx.net>" wrote: > Should this work? > > struct V(string s) { > } > > struct S(int U) { > V!"xyz" x; > alias x this; > } > > void main() { > S!10 a; > static assert(is(a : V!Args, Args...)); > } > > With DMD Git master, the static assert() fails. Should it? Am I doing > something wrong? How can I test whether something is implicitly > convertible to any instance of a particular template? There is no way other than checking for compile-time duck typing (see the implementations of isInputRange and others). One reason is that the compiler does not have the concept of "an instance of a template". Templates are for code generation and only the end-result (i.e. S!10) lives as a concept when compiling. Ali |
March 15, 2015 Re: Testing implicit conversion to template instance with is() expression | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Sunday, 15 March 2015 at 16:44:14 UTC, Ali Çehreli wrote:
> On 03/15/2015 08:47 AM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm@gmx.net>" wrote:
>
> > Should this work?
> >
> > struct V(string s) {
> > }
> >
> > struct S(int U) {
> > V!"xyz" x;
> > alias x this;
> > }
> >
> > void main() {
> > S!10 a;
> > static assert(is(a : V!Args, Args...));
> > }
> >
> > With DMD Git master, the static assert() fails. Should it? Am
> I doing
> > something wrong? How can I test whether something is
> implicitly
> > convertible to any instance of a particular template?
>
> There is no way other than checking for compile-time duck typing (see the implementations of isInputRange and others).
>
> One reason is that the compiler does not have the concept of "an instance of a template". Templates are for code generation and only the end-result (i.e. S!10) lives as a concept when compiling.
The code contained a small mistake, I forgot a `typeof()`:
// static assert(is(a : V!Args, Args...));
// should be:
static assert(is(typeof(a) : V!Args, Args...));
This still fails, but it works when I change it to:
static assert(is(typeof(a) : S!Args, Args...));
This means I can indeed test whether something _is_ an instance of a template. It just doesn't take the `alias this` into account. So I guess that's a bug?
|
March 15, 2015 Re: Testing implicit conversion to template instance with is() expression | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz | On Sunday, 15 March 2015 at 16:53:34 UTC, Marc Schütz wrote:
> On Sunday, 15 March 2015 at 16:44:14 UTC, Ali Çehreli wrote:
>> On 03/15/2015 08:47 AM, "Marc =?UTF-8?B?U2Now7x0eiI=?= <schuetzm@gmx.net>" wrote:
>>
>> > Should this work?
>> >
>> > struct V(string s) {
>> > }
>> >
>> > struct S(int U) {
>> > V!"xyz" x;
>> > alias x this;
>> > }
>> >
>> > void main() {
>> > S!10 a;
>> > static assert(is(a : V!Args, Args...));
>> > }
>> >
>> > With DMD Git master, the static assert() fails. Should it? Am
>> I doing
>> > something wrong? How can I test whether something is
>> implicitly
>> > convertible to any instance of a particular template?
>>
>> There is no way other than checking for compile-time duck typing (see the implementations of isInputRange and others).
>>
>> One reason is that the compiler does not have the concept of "an instance of a template". Templates are for code generation and only the end-result (i.e. S!10) lives as a concept when compiling.
>
> The code contained a small mistake, I forgot a `typeof()`:
>
> // static assert(is(a : V!Args, Args...));
> // should be:
> static assert(is(typeof(a) : V!Args, Args...));
>
> This still fails, but it works when I change it to:
>
> static assert(is(typeof(a) : S!Args, Args...));
>
> This means I can indeed test whether something _is_ an instance of a template. It just doesn't take the `alias this` into account. So I guess that's a bug?
Ok, now I'm pretty sure:
class V(string s) {
}
class S(int U) : V!"xyz" {
}
void main() {
S!10 a;
static if(is(typeof(a) : V!Args, Args...))
pragma(msg, Args);
}
This works, and it even correctly infers `Args` to be `tuple("xyz")`. As `alias this` is supposed to be interchangeable with subtyping, it must be a bug.
|
March 15, 2015 Re: Testing implicit conversion to template instance with is() expression | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz | https://issues.dlang.org/show_bug.cgi?id=14286 In the meantime, does someone know of a suitable workaround? |
March 15, 2015 Re: Testing implicit conversion to template instance with is() expression | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz | On Sunday, 15 March 2015 at 17:03:42 UTC, Marc Schütz wrote: > https://issues.dlang.org/show_bug.cgi?id=14286 > > In the meantime, does someone know of a suitable workaround? I found the following workaround. Not beautiful, but it works: enum isValue(alias T) = __traits(compiles, typeof(T)); template isConvertibleToInstanceOf(alias From, alias To) if(isValue!From) { enum isConvertibleToInstanceOf = isConvertibleToInstanceOf!(typeof(From), To); } template isConvertibleToInstanceOf(From, alias To) if(!is(From == struct) && !is(From == class) && !is(From == interface)) { enum isConvertibleToInstanceOf = false; } template isConvertibleToInstanceOf(From, alias To) if(is(From == struct) || is(From == class) || is(From == interface)) { // workaround for https://issues.dlang.org/show_bug.cgi?id=14286 import std.typetuple : anySatisfy; enum aliasThisConvertible(string name) = isConvertibleToInstanceOf!(mixin("typeof(From." ~ name ~ ")"), To); enum isConvertibleToInstanceOf = anySatisfy!(aliasThisConvertible, __traits(getAliasThis, From)) || is(From : To!Args, Args...); } |
March 15, 2015 Re: Testing implicit conversion to template instance with is() expression | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz | On Sunday, 15 March 2015 at 18:33:32 UTC, Marc Schütz wrote: > On Sunday, 15 March 2015 at 17:03:42 UTC, Marc Schütz wrote: >> https://issues.dlang.org/show_bug.cgi?id=14286 >> >> In the meantime, does someone know of a suitable workaround? > > I found the following workaround. Not beautiful, but it works: > > enum isValue(alias T) = __traits(compiles, typeof(T)); > > template isConvertibleToInstanceOf(alias From, alias To) > if(isValue!From) > { > enum isConvertibleToInstanceOf = isConvertibleToInstanceOf!(typeof(From), To); > } > > template isConvertibleToInstanceOf(From, alias To) > if(!is(From == struct) && !is(From == class) && !is(From == interface)) > { > enum isConvertibleToInstanceOf = false; > } > > template isConvertibleToInstanceOf(From, alias To) > if(is(From == struct) || is(From == class) || is(From == interface)) > { > // workaround for https://issues.dlang.org/show_bug.cgi?id=14286 > import std.typetuple : anySatisfy; > enum aliasThisConvertible(string name) = isConvertibleToInstanceOf!(mixin("typeof(From." ~ name ~ ")"), To); > enum isConvertibleToInstanceOf = > anySatisfy!(aliasThisConvertible, __traits(getAliasThis, From)) || > is(From : To!Args, Args...); > } It works for your previous code example: static assert(isConvertibleToInstanceOf!(S!10, V)); // OK But this also works: static assert(!isConvertibleToInstanceOf!(S!10, V!"abc")); // OK Can be reduced to: struct Foo(int i) {} alias Foo1 = Foo!1; static assert(is(Foo!2 == Foo1!T, T...)); // OK I think it's another bug. |
March 15, 2015 Re: Testing implicit conversion to template instance with is() expression | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicolas Sicard | On Sunday, 15 March 2015 at 18:53:33 UTC, Nicolas Sicard wrote: > Can be reduced to: > struct Foo(int i) {} > alias Foo1 = Foo!1; > static assert(is(Foo!2 == Foo1!T, T...)); // OK > > I think it's another bug. Right, I've filed another report: https://issues.dlang.org/show_bug.cgi?id=14290 |
Copyright © 1999-2021 by the D Language Foundation