| |
| Posted by H. S. Teoh in reply to Basile B. | PermalinkReply |
|
H. S. Teoh
Posted in reply to Basile B.
| On Thu, May 12, 2022 at 12:13:32PM +0000, Basile B. via Digitalmars-d-learn wrote: [...]
> Problem is more (from https://dlang.org/spec/expression.html#is_expression)
>
> ```
> is ( Type : TypeSpecialization , TemplateParameterList )
> is ( Type == TypeSpecialization , TemplateParameterList )
> is ( Type Identifier : TypeSpecialization , TemplateParameterList )
> is ( Type Identifier == TypeSpecialization , TemplateParameterList )
> ```
>
> I never remember those variants, because basically you never need them... They were required for std.traits and that's it.
Not true. I use these all the time in generic code. Basically, they allow you to do IFTI-like template pattern-matching using static-if's. This is eminently useful for inspecting incoming types in template functions. For example, in serialization code, I would do something like:
auto serialize(T)(T data) {
static if (is(T == string))
{
... // straightforward string encoding
}
else static if (is(T : U[], U))
// this means: "T matches the pattern `U[]`,
// where U is some arbitrary type"
{
... // non-string array encoding
// note that in this block, `U` is defined to be
// the array element; very convenient for
// further type dissection
}
else static if (is(T : U[V], U, V))
// this means: "T matches the pattern `U[V]`,
// where U and V are arbitrary types"
{
... // AA encoding
// similarly, in this block U is the value type
// and V is the key type, very convenient for
// further type dissection
}
else static if (is(T : MyType!(U), string U))
// this means: "T matches the pattern
// `MyType!(U)` where U is some string"
{
... // special handling for instantiations of
// MyType with string argument
// in this block, U == string
}
... // and so on
}
I concede that the documentation isn't exactly easy to understand on a first read; it took me many tries before it "clicked". But once you understand the general pattern, most of the cases make sense and is pretty predictable.
There *are* one or two special cases, granted, but those are exceptional and there are already std.traits wrappers that expose a friendlier API. The worst offender in this category is __parameters, about which I wrote years ago here:
https://forum.dlang.org/thread/vpjpqfiqxkmeavtxhyla@forum.dlang.org
Still, putting this ugly special case aside, the rest of is(...) syntax mostly conforms to the above pattern, and is readily understandable once you learn the pattern.
T
--
Written on the window of a clothing store: No shirt, no shoes, no service.
|