As well as:
is (T : class)
is (T : interface)
is (T : union)
This could be useful in two scenarios:
The case where T represents a enum instance of said type. For example:
struct T {}
enum E : T {a = T.init}
In this case, E being an enum, it isn't a struct, however, it would be useful to know if it can "decay" to a struct type. This syntax would make proper enum handling correct "by default" rather than explicitly, EG:
is (T : struct)
vs
is (OriginalType!T == struct)
This (I think), is actually quite important, as it increases the chances of code being correct with no special extra content, as well as lower the overall complexity.
Another case where this could be useful, is if T defines an alias this that resolves to another type:
class C
{
T t;
alias t this;
}
is (T == struct); //false
is (T : struct); //true
Related conversation:
http://forum.dlang.org/thread/[email protected]
Also, as a general rule, it's more consistent. If:
is (T : U);
is legal, then so should:
is (T : struct);
Comment #1 by monarchdodra — 2013-09-25T08:55:45Z
Also, use case that we might want to support (but I'm not 100% sure on this):
is (typeof(f) : delegate)
idea being that a function is also a delegate (?) Not entirely sure this is actually true though. Still, a struct might be implicitly castable via alias this to a delegate, so ": delegate" and ": function" would be useful.
See also:
http://d.puremagic.com/issues/show_bug.cgi?id=11123
This might have been avoided with useage of ": delegate" as opposed to "== delegate"
Comment #2 by k.hara.pg — 2013-09-25T09:06:36Z
(In reply to comment #0)
> Another case where this could be useful, is if T defines an alias this that
> resolves to another type:
>
> class C
> {
> T t;
> alias t this;
> }
>
> is (T == struct); //false
> is (T : struct); //true
Mistake of:
is (C == struct); //false
is (C : struct); //true
?
And, how this will work when multiple alias this is properly implemented?
Comment #3 by andrej.mitrovich — 2013-09-25T09:24:35Z
(In reply to comment #2)
> And, how this will work when multiple alias this is properly implemented?
I think we should think about adding a new 'is' expression for alias this checks, because I've already ran into an issue with them interfering with the is(T : X) syntax. I'm thinking we could introduce something like the following:
if (is(T : alias X)) => T has a subtype of type X
I can't find my other bug report right now where I mention this, I'll look into it later.
Comment #4 by monarchdodra — 2013-09-25T09:53:24Z
(In reply to comment #2)
> And, how this will work when multiple alias this is properly implemented?
I don't understand the problem? Isn't it the same as, say: "is (C : int)"?
I don't see what is so special about struct:
class C
{
T t;
int i;
alias t this;
alias i this;
}
is (C == struct); //false
is (C == int); //false
is (C : struct); //true
is (C : int); //true
Or am I missing something obvious? Apologies in advance.
> I've already ran into an issue with them interfering with the
is(T : X) syntax
Isn't the point that they *do* interfere with such syntax?
Comment #5 by monarchdodra — 2013-09-25T09:59:46Z
(In reply to comment #2)
> (In reply to comment #0)
> > Another case where this could be useful, is if T defines an alias this that
> > resolves to another type:
> >
> > class C
> > {
> > T t;
> > alias t this;
> > }
> >
> > is (T == struct); //false
> > is (T : struct); //true
>
> Mistake of:
>
> is (C == struct); //false
> is (C : struct); //true
>
> ?
Yes. Sorry. Your code is correct.
Comment #6 by k.hara.pg — 2013-09-25T10:33:27Z
(In reply to comment #4)
> (In reply to comment #2)
> > And, how this will work when multiple alias this is properly implemented?
>
> I don't understand the problem? Isn't it the same as, say: "is (C : int)"?
Today,
1. is(T U == super) captures the super class list of T in U.
class C : Object {}
static if (is(C U == super)) { static assert(is(U[0] == Object)); }
2. If T is implicitly convertible to U, is(T X : U) captures T in X.
Then, if multiple alias this is supported:
struct S1 {}
struct S2 {}
struct S {
S1 s1; alias s1 this;
S2 s2; alias s2 this;
}
static if (is(S U : struct)) { /* What's captured in U? */ }
Based on the #1, U would capture the tuple of S1 and S2.
Based on the #2, U would capture the type S.
Which is chosen? Or other choices?
Comment #7 by monarchdodra — 2013-09-25T12:23:05Z
(In reply to comment #6)
> (In reply to comment #4)
> > (In reply to comment #2)
> > > And, how this will work when multiple alias this is properly implemented?
> >
> > I don't understand the problem? Isn't it the same as, say: "is (C : int)"?
>
> Today,
> 1. is(T U == super) captures the super class list of T in U.
>
> class C : Object {}
> static if (is(C U == super)) { static assert(is(U[0] == Object)); }
>
> 2. If T is implicitly convertible to U, is(T X : U) captures T in X.
>
> Then, if multiple alias this is supported:
>
> struct S1 {}
> struct S2 {}
> struct S {
> S1 s1; alias s1 this;
> S2 s2; alias s2 this;
> }
> static if (is(S U : struct)) { /* What's captured in U? */ }
>
> Based on the #1, U would capture the tuple of S1 and S2.
> Based on the #2, U would capture the type S.
>
> Which is chosen? Or other choices?
I'm no expert with "is", but isn't "is(C U == super)" a special case of "is"? (which would look much better as a trait too?)
For example, when I do this;
//----
struct S
{
short i;
alias i this;
}
class C
{
S s;
alias s this;
}
void main()
{
static if (is(C U : int))
static assert(is(U == C)); //Base type C is captured
}
//----
If C was to actually to be:
class C
{
S s1;
S s2;
alias s1 this;
alias s2 this;
}
I don't see how it would affect my above static if.
Since I don't really see ": int" as any different from ": struct", then to your question, I answer: #2, U would capture the type S.
But I'm no "is" expert.
Comment #8 by robert.schadek — 2024-12-13T18:12:06Z