Motive behind !empty() with front() instead of Optional front()

Q. Schroll qs.il.paperinik at gmail.com
Sat Apr 10 02:14:58 UTC 2021


On Friday, 9 April 2021 at 21:17:03 UTC, Paul Backus wrote:
> On Friday, 9 April 2021 at 20:40:54 UTC, Q. Schroll wrote:
>>
>> As Andrei said, in C++, apart from the `decltype` exception 
>> (which is justified), references behave as aliases. In D, it's 
>> the same, apart from `__trais(isRef)` which is also justified. 
>> What else do you expect from a reference object? Maybe I'm 
>> biased, but I don't see how other solutions than C++'s would 
>> be better.
>
> Hypothetically, if `ref` were a type qualifier, I'd expect it 
> to behave the same way as D's other type qualifiers. We don't 
> strip `const` or `shared` from types during template 
> instantiation (the special case of `const(T[])` → `const(T)[]` 
> notwithstanding), so my baseline expectation is that we 
> wouldn't strip `ref` either.
>
> Maybe there's an argument to be made that this is a bad idea, 
> and that you should always be able to replace an lvalue with a 
> reference without any effect on the program's behavior. But I 
> don't think you can take it as given that that's *obviously* 
> the correct way to do references, just because that's what C++ 
> does.

The "special case of `const`" is exactly the point: If you have a 
`const(T[]) ts` object and you do
```D
auto ts2 = ts;
```
then, `typeof(ts2)` is `const(T)[]`. The whole point of making a 
copy is that it (or at least the first layer) becomes independent 
and mutable. I think references should behave the same: Assigning 
a `ref(T)` to an `auto` variable should create a copy that (or at 
least the first layer) is independent of the source. Creating 
another reference is near-useless.
When it comes to parameter passing, binding by copy is expected 
to be the default and binding by reference a specialty. One 
reason being that binding by copy is more flexible, e.g. it 
allows (implicit) conversions.

I don't think it's obviously the right way because C++ does it 
that way, but it's a hint. I came to the conclusion myself; 
thinking of various alternatives, I could see obvious problems. 
C++'s references have (obvious?) problems, so it's not like it's 
perfect. IMO, `ref` as a storage class is the Right Thing. D 
falls short in some places:
* Allowing `ref` for local variables would be valuable at times. 
There's no actual gain in not allowing them. Some stuff like 
postfix operators even lower to `ref` local variables.
* One cannot directly express `ref` returning delegate or 
function pointer types on many occasions, e.g. neither `is(DG == 
ref int delegate())` nor `is(DG == int delegate() ref)` compile. 
Also, one cannot directly specify `ref` returning delegate or 
function pointer types in parameter lists. In both cases, an 
alias has to be defined.

If `ref` were a type constructor, these would be non-issues for 
sure. But we're nowhere near *requiring* it to be one to solve 
these.


More information about the Digitalmars-d mailing list