On Sat, 18 Sep 2010 05:15:38 -0400, Jonathan M Davis <jmdavisp...@gmx.com> wrote:

Okay, if I try and compile the following program.

struct S
{
    @property S save() const
    {
        return this;
    }

    int[] _val;
}

void main()
{
}


I get the error message

d.d(5): Error: cannot implicitly convert expression (this) of type const(S) to S

Yes, because you are converting "this" from a const(S) to an S to return it.

Try:

@property const(S) save() const
{
   return this;
}


If I remove const from save(), then it works, but with const there, it doesn't. If I change _val to int or a struct type which does not contain an array, it works. If I change _val to a struct type which has a member variable which is an
array, it doesn't work.

Because arrays are reference types.

You can implicitly convert a const(int) to an int because it's not a reference type. But you can't implicitly convert a const(int *) to an int * because it's a reference type.

That axiom of implicit conversion is propagated to structs as well -- if a struct has only value types, then it can be implicitly converted, reference types cannot.

I'll give you an example of why your version should not work. Let's say it *did* compile, then this function is allowed to violate const:

void foo(const(S) s)
{
   S s2 = s.save;
   s2._val[0]++;
assert(s2._val[0] == s._val[0]); // oops, I modified s._val[0], but s is const!
}

From the looks of it, there's something about having an array as a member
variable which makes this blow up. Perhaps it has to do with the fact that _val
is a reference type and would be shared? Do I need to declare a postplit
constructor to fix this? Declaring one doesn't seem to help, but maybe I just
don't know how to declare them correctly.

In reality, you cannot make save const, unless you want to do a deep copy (but I recommend against that, save should be a quick operation).

The solution is actually inout. With inout, you can assert that save does not modify the data, but that it doesn't alter the constancy of the actual type.

@property inout(S) save() inout
{
  return this;
}

Should work for S, const(S) and immutable(S).

However, inout doesn't work at all right now. Please vote for bug http://d.puremagic.com/issues/show_bug.cgi?id=3748 (oh wait, you already did, but others should too :)

-Steve

Reply via email to