January 10, 2021
On Sunday, 10 January 2021 at 14:40:04 UTC, kdevel wrote:
> On Sunday, 10 January 2021 at 10:42:48 UTC, Jonathan M Davis wrote:
>
> [...]
>
>> IIRC, if the class overrides opCast for bool, then
>>
>>     if(c)
>>
>> will cast the object to bool and use the result for the if condition,
>
> Well, no:
>
> ```null.d
> import std.stdio: writeln;
> class C {
>    bool opCast ()
>    {
>       return true;
>    }
> }

Your opCast has the wrong signature. It should be:

    bool opCast(T : bool)()
January 10, 2021
On Sunday, 10 January 2021 at 16:44:29 UTC, Paul Backus wrote:

[...]

> Your opCast has the wrong signature.

"Wrong" in what respect?

> It should be:
>
>     bool opCast(T : bool)()

"My" opCast works as expected:

```null2.d
import std.stdio: writeln;
class C {
   int i;
   bool opCast ()
   {
      __PRETTY_FUNCTION__.writeln;
      return true;
   }
}

void bar (C c)
{
   if (c) writeln (3);
   else writeln (2);
}

void foo (ref C c)
{
   if (c) writeln (5);
   else writeln (4);
}

void main ()
{
   C c = new C;
   writeln (c);
   if (c) writeln (1);
   else writeln (0);
   bar (c);
   foo (c);
   cast (bool) c; // print bool null2.C.opCast()
   c = null;
   cast (bool) c; // Segmentation fault
}
```

$  dmd null2 && ./null2
null2.C
1
3
5
bool null2.C.opCast()
Segmentation fault


January 10, 2021
On Sunday, 10 January 2021 at 10:42:48 UTC, Jonathan M Davis wrote:
> IIRC, if the class overrides opCast for bool, then
>
>     if(c)
>
> will cast the object to bool and use the result for the if condition, whereas
>
>     if(c !is null)
>
> always checks whether the reference is null.

You're misremembering. Or maybe it was changed since you last checked. A rewrite from `if (c)` to `if (c.opCast!bool)` "only happens, however, for instances of structs. Class references are converted to bool by checking to see if the class reference is null or not."

https://dlang.org/spec/operatoroverloading.html#boolean_operators
January 10, 2021
On Sunday, 10 January 2021 at 17:28:42 UTC, kdevel wrote:
> On Sunday, 10 January 2021 at 16:44:29 UTC, Paul Backus wrote:
>
> [...]
>
>> Your opCast has the wrong signature.
>
> "Wrong" in what respect?
>

It does not match the signature required by the language spec:

https://dlang.org/spec/operatoroverloading.html#cast
January 10, 2021
On Sunday, 10 January 2021 at 19:21:47 UTC, Paul Backus wrote:
> On Sunday, 10 January 2021 at 17:28:42 UTC, kdevel wrote:
>> On Sunday, 10 January 2021 at 16:44:29 UTC, Paul Backus wrote:
>>
>> [...]
>>
>>> Your opCast has the wrong signature.
>>
>> "Wrong" in what respect?
>>
>
> It does not match the signature required by the language spec:
>
> https://dlang.org/spec/operatoroverloading.html#cast

Sure, but it is called anyway:

```null3.d
import std.stdio: writeln;
class C {
   int i;
   bool opCast ()
   {
      __PRETTY_FUNCTION__.writeln;
      return false;
   }
}

void main ()
{
   C c = new C;
   cast (bool) c; // print bool null3.C.opCast()
   c = null;
   cast (bool) c; // Segmentation fault
}
```

$ dmd null3 && ./null3
bool null3.C.opCast()
Segmentation fault

As ag0aep6g pointed out

   if (c)

does not invoke the opCast member. Neither one of the signatures

   bool opCast ()
   T opCast (T: bool) ().

This "conversion to bool" [1] of the class variable seems to be not
programmatically accessible.

[1] "Class references are converted to bool by checking to see if the class reference is null or not." from § 20.2.1
January 11, 2021
On Thursday, 7 January 2021 at 04:57:55 UTC, 12345swordy wrote:
> if (c !is null) Why?????
>
> Would it be simpler to type
>
> if (c is not null)
>
> on a related note. Why are not we allowed to do this?
>
> if (c != null)
>
> when other languages such as c#/java allow for it?
>
> -Alex

One thing you could do is to make an "extension method", exploit ufcs and do like c.isNull instead.

Maybe those already exists somewhere.

For reference, in C# we have null-conditional and null-coalescing operators. Also, strings for example have string.IsNullOrEmpty and IsNullOrWhiteSpace, those are handy.
January 11, 2021
On 1/10/21 4:52 PM, kdevel wrote:
> On Sunday, 10 January 2021 at 19:21:47 UTC, Paul Backus wrote:
>> On Sunday, 10 January 2021 at 17:28:42 UTC, kdevel wrote:
>>> On Sunday, 10 January 2021 at 16:44:29 UTC, Paul Backus wrote:
>>>
>>> [...]
>>>
>>>> Your opCast has the wrong signature.
>>>
>>> "Wrong" in what respect?
>>>
>>
>> It does not match the signature required by the language spec:
>>
>> https://dlang.org/spec/operatoroverloading.html#cast
> 
> Sure, but it is called anyway:
> 
> ```null3.d
> import std.stdio: writeln;
> class C {
>     int i;
>     bool opCast ()
>     {
>        __PRETTY_FUNCTION__.writeln;
>        return false;
>     }
> }
> 
> void main ()
> {
>     C c = new C;
>     cast (bool) c; // print bool null3.C.opCast()
>     c = null;
>     cast (bool) c; // Segmentation fault
> }
> ```
> 
> $ dmd null3 && ./null3
> bool null3.C.opCast()
> Segmentation fault
> 
> As ag0aep6g pointed out
> 
>     if (c)
> 
> does not invoke the opCast member. Neither one of the signatures
> 
>     bool opCast ()
>     T opCast (T: bool) ().
> 
> This "conversion to bool" [1] of the class variable seems to be not
> programmatically accessible.
> 
> [1] "Class references are converted to bool by checking to see if the class reference is null or not." from § 20.2.1

That's a relic from D1: https://digitalmars.com/d/1.0/operatoroverloading.html#Unary

IMO, that functionality should not be used, but I doubt we will ever remove it. (I tested, and using this form works for if(s) for a struct)

Note also that assert(c) will check the invariant of the object if it's not null.

D has a few hidden behaviors for truthiness.

-Steve
1 2
Next ›   Last »