April 09
https://issues.dlang.org/show_bug.cgi?id=24491

          Issue ID: 24491
           Summary: Introduce `is` [keyword] expressions
           Product: D
           Version: D2
          Hardware: All
                OS: All
            Status: NEW
          Severity: enhancement
          Priority: P1
         Component: dmd
          Assignee: nobody@puremagic.com
          Reporter: qs.il.paperinik@gmail.com

Currently, `is` can be used in two ways: As a binary operator as in `lhs is rhs` or for type stuff as in `is(T == S)`.

In the latter one, we can use `is(T == [keyword])`, where the keyword is `struct`, `class` and whatnot. These really feel wrong. A class type is not equal to `class`. Because `class` is a keyword, why not introduce `T is class`? Effectively, `is class`, `is interface`, `is struct`, `is union`, `is function`, `is delegate`, `is ref`, `is out`, `is in`, `is return`, `is enum`, `is alias`, `is static`, `is const`, `is immutable`, `is shared`, and probably more, could be seen more like a post-fix operator, but would still be parsed as a binary `is`.

Some of them make sense for both types and objects, where for objects, they
just test the type, similar to how `sizeof` works:
E.g., if `T` is a template type parameter and `t` is of type `T`, `T is const`
is a synonym for `is(T == const)`, and `t is const` becomes `is(typeof(t) ==
const)`.
Some of these, IMO, make sense only for types (e.g. `is class`), and some
require an object, e.g. `is scope` or the parameter storage class tests `is
ref`, `is in`, `is out`, `is return`. Some take a symbol such as `is enum` and
`is alias`.
Some of these group together: Type category tests, type constructor tests, and
parameter storage class tests.
Each category could be allowed to be OR-connected: `T is (class|interface)`.
For that, I’d allow parentheses around single-keyword tests as well, to aid
CTFE code generation, not because I’d expect someone to actually write `T is
(class)`.

Thinking about it, for template parameters, instead of `template Templ(T) if (T
is (class|interface))` why not put the constraint directly next to `T`? As in:
`template Templ(class|interface T)`; at least for aggregate categories that
makes sense.

--