| |
 | Posted by Jonathan M Davis in reply to Quirin Schroll | Permalink Reply |
|
Jonathan M Davis 
Posted in reply to Quirin Schroll
| On Friday, June 27, 2025 10:31:42 AM Mountain Daylight Time Quirin Schroll via Digitalmars-d-learn wrote:
> On Tuesday, 24 June 2025 at 02:05:40 UTC, Jonathan M Davis wrote:
> > There's also the issue of templated code. If an attribute is
> > desirable in the cases where it works, and it's fine for it to
> > be ignored in the cases where it doesn't apply, then that means
> > that you can have code such as
> > ```d
> > scope T foo;
> > ```
> > or
> > ```d
> > pure T foo;
> > ```
> > without having to worry about whether the attribute works with
> > a particular T.
> >
> > On the other hand, if it's an error for the attribute to be
> > applied, then the code will need to do something like use a
> > static if to apply the attribute, e.g.
> > ```d
> > static if(isPointer!T || is(T == class) ||
> > isDynamicArray!T || isAssociativeArray!T)
> > {
> > scope T foo;
> > }
> > else
> > T foo;
> > ```
> > and of course, if you get the check wrong, then the attribute
> > won't be applied properly.
>
> Getting the check wrong is fairly easy. The following cases are
> missing: `is(T == interface)`, `is(T == delegate)`, and maybe
> `is(typeof(*T.init) == function)` (I don’t know if `isPointer`
> catches function pointers). I’m not even sure those are all the
> missing cases.
Yeah. I'd have to sit down and work through it to make sure that I found all of the cases. I just listed what I could think of off the top of my head, and this is the sort of thing where it's really easy to get it wrong.
Looking at std.traits.hasIndirections, it lists what we've already mentioned plus types with context a pointer. And hasIndirections would _almost_ be the thing to use, but it also looks at the member variables. So, if you have a struct with a pointer, it would be true, whereas scope would have no effect on it, since from what I recall scope only goes one level deep.
If we were going to make it so that scope were illegal on types where it had no effect, we'd either have to provide a trait for it that handled all of the cases, or you'd have to write out a condition that tried to put scope on a variable of that type to check whether it would compile, e.g.
static if(is(typeof((){ scope T foo; })))
scope T foo;
else
T foo;
Either way, templated code is just much easier and less error-prone to write if scope is ignored if it doesn't do anything, much as that might be confusing or annoying in some situations.
- Jonathan M Davis
|