Thread overview
Regarding opCast(bool) class method
Nov 08, 2012
bearophile
Nov 09, 2012
Regan Heath
Nov 09, 2012
bearophile
November 08, 2012
I think that now and then it's good to underline some D issues, even old ones.

This little program shows the asymmetry in opCast(bool) between struct instances and class instances:


struct FooStruct {
    int x;
    this(int xx) { this.x = xx; }
    T opCast(T: bool)() {
        return this.x != 0;
    }
}

class FooClass {
    int x;
    this(int xx) { this.x = xx; }
    T opCast(T: bool)() {
        return this.x != 0;
    }
}

void main() {
    import std.stdio;
    enum int N = 0;

    auto fstruct = FooStruct(N);
    if (fstruct)
        writeln("fstruct true");
    else
        writeln("fstruct false"); //*

    if (cast(bool)fstruct)
        writeln("cast(bool)fstruct true");
    else
        writeln("cast(bool)fstruct false"); //*

    auto fclass = new FooClass(N);

    if (fclass)
        writeln("fclass true"); //*
    else
        writeln("fclass false");

    if (cast(bool)fclass)
        writeln("cast(bool)fclass true");
    else
        writeln("cast(bool)fclass false"); //*
}



The output:

fstruct false
cast(bool)fstruct false
fclass true
cast(bool)fclass false


Is this situation a problem?
If in your code you convert a struct to class or the other way, and it contains an opCast(bool), you will have troubles. And generally I don't like how opCast(bool) works in classes, I think it's a bit bug-prone. I think "if(fclass)" and "if(cast(bool)fclass)" should always have the same boolean value.

If this situation is a problem, then here are two of the possible solutions:
- Do not allow opCast(bool) in classes. How much often do you need cast(bool) on class instances?
- Keep cast(bool) in classes, and remove the asymmetry between structs and classes, if possible. So "if(fclass)" on a class instance calls opCast(bool). Then to test the value of the reference you use "if(fclass is null)".


See also my issue on this:
http://d.puremagic.com/issues/show_bug.cgi?id=3926

More info on related matters in C++/C++11:
http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_conversion_operators
http://www.artima.com/cppsource/safeboolP.html
http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Safe_bool

Bye,
bearophile
November 09, 2012
On Thu, 08 Nov 2012 23:04:17 -0000, bearophile <bearophileHUGS@lycos.com> wrote:
> If this situation is a problem, then here are two of the possible solutions:
> - Do not allow opCast(bool) in classes. How much often do you need cast(bool) on class instances?

I don't like it, it restricts people from defining a class which represents a boolean value/state (and casting it to bool).

> - Keep cast(bool) in classes, and remove the asymmetry between structs and classes, if possible. So "if(fclass)" on a class instance calls opCast(bool). Then to test the value of the reference you use "if(fclass is null)".

This is a breaking change.

A slightly less breaking change would be to make "if (fclass)" into both a reference !is null check and a call to any opCast(bool) if it exists.  This would then only break existing code using "if (fclass)" on references to classes which define opCast(bool) (which return false).

R

-- 
Using Opera's revolutionary email client: http://www.opera.com/mail/
November 09, 2012
Regan Heath:

> This is a breaking change.

Yes, I have several requests that cause tiny breaking changes open in Bugzilla, since years, and they often have had no comments for years. Sometimes breaking little things is better.

Bye,
bearophile