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

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Thu Apr 8 02:18:23 UTC 2021


On 4/7/21 5:31 PM, Q. Schroll wrote:
> 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`.

Very well put, thank you.



More information about the Digitalmars-d mailing list