Error: cannot implicitly convert expression (this) of type const(S) to S
Steven Schveighoffer
schveiguy at yahoo.com
Sat Sep 18 09:58:15 PDT 2010
On Sat, 18 Sep 2010 05:15:38 -0400, Jonathan M Davis <jmdavisProg at 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
More information about the Digitalmars-d-learn
mailing list