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

Q. Schroll qs.il.paperinik at gmail.com
Wed Apr 7 21:31:38 UTC 2021


On Tuesday, 6 April 2021 at 02:14:17 UTC, Paul Backus wrote:
> On Tuesday, 6 April 2021 at 01:47:47 UTC, Q. Schroll wrote:
>> On Friday, 26 March 2021 at 15:12:04 UTC, Paul Backus wrote:
>>> Of course the ideal would be to make `ref` itself into a type 
>>> qualifier (`ref(T)`).
>>
>> If you look at all the exceptions C++ has for its reference 
>> type constructor, you'll immediately see why Walter created 
>> `ref` as a storage class and not a type constructor. C++ 
>> reference types in many cases don't compose; e.g. 
>> `vector<int&>` isn't a thing.
>> If you really think about it, you don't need `ref` as a type 
>> constructor. Although allowing `ref` local variables wouldn't 
>> be harmful, I guess.
>
> Here's what the generic identity function currently looks like 
> in D:
>
>     auto ref T identity(T)(auto ref T arg)
>     {
>         import core.lifetime: forward;
>         return forward!arg;
>     }
>
> Here's what the generic identity function *would* look like if 
> `ref` were a type qualifier:
>
>     T identity(T)(T arg)
>     {
>         return arg;
>     }
>
> I rest my case.

In C++, the identity function is
```C++
template<typename T>
T&& identitiy(T&& arg)
{
     return std::forward<T>(arg);
}
```
if you want it to work like `identity(arg)`.

**TL;DR:** C++ doesn't do it the simple way for a reason.

If you do
```C++
template<typename T>
T identitiy(T arg)
{
     return arg;
}
```
you get copies unless you call it `identity<int&>(arg)` and 
`identity<int&&>(1)` (which defeats the purpose, I guess.

Template type deduction alone (C++ has 4 different rule sets 
about type deduction) is complicated. One reason for stripping 
`ref` from the argument types unless they explicitly bind to 
`ref` parameters is that references should act like aliases:
```C++
int i;
int& r = i;
f(i);
f(r);
```
Here, `f(r)` should act the same as `f(i)` irrespective of how 
`f` is defined. `f` could take `int`, `int&`, `const int&`, or 
`T`, `const T&`, or `T&&` for some `T` that can implicitly 
constructed from `int`. For `int&&` or `T&`it wouldn't compile. 
References as type constructors are weird. And please note, this 
is what I *immediately* could come up with and I verified. 
There's stuff with function types and static array bounds that I 
remember have shenanigans with references, but I'd have to do 
some search for details.

The only thing D does wrong in this regard is not having 
`forward` and `move` in `object.d`.


More information about the Digitalmars-d mailing list