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/vpjpqfiqxkmeavtxh...@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.

Reply via email to