Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
January 29, 2016 is(some template instantiation) is true, but the actual instantiation fails | ||||
---|---|---|---|---|
| ||||
Code: ---- struct HasFoo { void foo() {} } struct NoFoo {} struct CallsFoo(T) { T t; void bar() { t.foo(); } } static assert(is(CallsFoo!HasFoo)); alias Bar = CallsFoo!HasFoo; static assert(is(CallsFoo!NoFoo)); // (1) //alias Baz = CallsFoo!NoFoo; // (2) ---- This compiles, although I expected that (1) should fail. Now try uncommenting (2) and it can't be compiled. Why does `is(CallsFoo!NoFoo)` evaluate to true if `is(CallsFoo!NoFoo)` can't be instantiated? Am I missing something about `is(T)` or is it a bug? How can I reliably test if CallsFoo can be instantiated? |
January 29, 2016 Re: is(some template instantiation) is true, but the actual instantiation fails | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adrian Matoga | On Friday, 29 January 2016 at 15:28:29 UTC, Adrian Matoga wrote:
> How can I reliably test if CallsFoo can be instantiated?
You can use a constraint to prevent invalid instantiation:
struct HasFoo { void foo() {} }
struct NoFoo {}
struct CallsFoo(T)
if (__traits(hasMember, T, "foo"))
{
T t;
void bar() { t.foo(); }
}
static assert(is(CallsFoo!HasFoo));
static assert(!is(CallsFoo!NoFoo));
|
January 29, 2016 Re: is(some template instantiation) is true, but the actual instantiation fails | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adrian Matoga | On 1/29/16 10:28 AM, Adrian Matoga wrote:
> Code:
>
> ----
> struct HasFoo { void foo() {} }
>
> struct NoFoo {}
>
> struct CallsFoo(T) {
> T t;
> void bar() { t.foo(); }
> }
>
> static assert(is(CallsFoo!HasFoo));
> alias Bar = CallsFoo!HasFoo;
>
> static assert(is(CallsFoo!NoFoo)); // (1)
> //alias Baz = CallsFoo!NoFoo; // (2)
> ----
>
> This compiles, although I expected that (1) should fail.
> Now try uncommenting (2) and it can't be compiled.
>
> Why does `is(CallsFoo!NoFoo)` evaluate to true if `is(CallsFoo!NoFoo)`
> can't be instantiated?
> Am I missing something about `is(T)` or is it a bug?
> How can I reliably test if CallsFoo can be instantiated?
>
is(T) is supposed to be false if T is not a valid type.
I would agree with you that the static assert should fail.
-Steve
|
January 29, 2016 Re: is(some template instantiation) is true, but the actual instantiation fails | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Friday, 29 January 2016 at 16:36:01 UTC, Steven Schveighoffer wrote: > On 1/29/16 10:28 AM, Adrian Matoga wrote: >> Code: >> >> ---- >> struct HasFoo { void foo() {} } >> >> struct NoFoo {} >> >> struct CallsFoo(T) { >> T t; >> void bar() { t.foo(); } >> } >> >> static assert(is(CallsFoo!HasFoo)); >> alias Bar = CallsFoo!HasFoo; >> >> static assert(is(CallsFoo!NoFoo)); // (1) >> //alias Baz = CallsFoo!NoFoo; // (2) >> ---- >> >> This compiles, although I expected that (1) should fail. >> Now try uncommenting (2) and it can't be compiled. >> >> Why does `is(CallsFoo!NoFoo)` evaluate to true if `is(CallsFoo!NoFoo)` >> can't be instantiated? >> Am I missing something about `is(T)` or is it a bug? >> How can I reliably test if CallsFoo can be instantiated? >> > > is(T) is supposed to be false if T is not a valid type. > > I would agree with you that the static assert should fail. > > -Steve Oh, there's more: // this should fail: static assert(is(CallsFoo!NoFoo)); // this should fail too: static assert(is(typeof({ alias Baz = CallsFoo!NoFoo; return Baz.init; }()))); // and this: static assert(__traits(compiles, { alias Baz = CallsFoo!NoFoo; return Baz.init; }())); // but only this fails: alias Baz = CallsFoo!NoFoo; https://issues.dlang.org/show_bug.cgi?id=15623 |
January 29, 2016 Re: is(some template instantiation) is true, but the actual instantiation fails | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adrian Matoga | On Friday, 29 January 2016 at 17:01:46 UTC, Adrian Matoga wrote:
> On Friday, 29 January 2016 at 16:36:01 UTC, Steven Schveighoffer wrote:
>> On 1/29/16 10:28 AM, Adrian Matoga wrote:
>>>[...]
>>
>> is(T) is supposed to be false if T is not a valid type.
>>
>> I would agree with you that the static assert should fail.
>>
>> -Steve
>
> Oh, there's more:
> // this should fail:
> static assert(is(CallsFoo!NoFoo));
> // this should fail too:
> static assert(is(typeof({ alias Baz = CallsFoo!NoFoo; return Baz.init; }())));
> // and this:
> static assert(__traits(compiles, { alias Baz = CallsFoo!NoFoo; return Baz.init; }()));
> // but only this fails:
> alias Baz = CallsFoo!NoFoo;
>
> https://issues.dlang.org/show_bug.cgi?id=15623
Haven't you seen my answer about constraint ?
If you put a constraint on your function template then invalid instantiations are rejected. I mean... this language feature is not just ornamental...
What do you think constraints are used for otherwise ^^
|
January 29, 2016 Re: is(some template instantiation) is true, but the actual instantiation fails | ||||
---|---|---|---|---|
| ||||
Posted in reply to Basile B. | On 1/29/16 6:44 PM, Basile B. wrote:
>
> Haven't you seen my answer about constraint ?
>
> If you put a constraint on your function template then invalid
> instantiations are rejected. I mean... this language feature is not just
> ornamental...
>
> What do you think constraints are used for otherwise ^^
A constraint should not be necessary here. Constraints are useful when you have multiple templates that may match (without specializations), or you want to affect the way the compiler reports errors.
Iff a template instantiation T compiles, then is(T) should evaluate to true. At least, that's my understanding.
-Steve
|
January 29, 2016 Re: is(some template instantiation) is true, but the actual instantiation fails | ||||
---|---|---|---|---|
| ||||
Posted in reply to Adrian Matoga | On 01/29/2016 09:01 AM, Adrian Matoga wrote: > Oh, there's more: > // this should fail: > static assert(is(CallsFoo!NoFoo)); > // this should fail too: > static assert(is(typeof({ alias Baz = CallsFoo!NoFoo; return Baz.init; > }()))); > // and this: > static assert(__traits(compiles, { alias Baz = CallsFoo!NoFoo; return > Baz.init; }())); > // but only this fails: > alias Baz = CallsFoo!NoFoo; > > https://issues.dlang.org/show_bug.cgi?id=15623 As I noted on the bug report, they are work when moved from module scope to inside a function (e.g. main()). At least there's that workaround... Ali |
January 30, 2016 Re: is(some template instantiation) is true, but the actual instantiation fails | ||||
---|---|---|---|---|
| ||||
Posted in reply to Basile B. | On Friday, 29 January 2016 at 23:44:56 UTC, Basile B. wrote:
> Haven't you seen my answer about constraint ?
>
> If you put a constraint on your function template then invalid instantiations are rejected. I mean... this language feature is not just ornamental...
>
> What do you think constraints are used for otherwise ^^
Yes, I've seen it, thanks.
Requiring the user to write the constraint might indeed enforce a better style, but I want to be able to test it even if the user forgets the constraint. Otherwise she'll get cryptic error messages from some other code assuming that CallsFoo!NoFoo is a valid type.
|
January 30, 2016 Re: is(some template instantiation) is true, but the actual instantiation fails | ||||
---|---|---|---|---|
| ||||
Posted in reply to Ali Çehreli | On Saturday, 30 January 2016 at 00:16:21 UTC, Ali Çehreli wrote:
> > https://issues.dlang.org/show_bug.cgi?id=15623
>
> As I noted on the bug report, they are work when moved from module scope to inside a function (e.g. main()). At least there's that workaround...
>
> Ali
Thanks a lot! Now I can continue my work. :)
|
Copyright © 1999-2021 by the D Language Foundation