Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
June 18, 2007 Difference betwee storage class and type (invariant/const)? | ||||
---|---|---|---|---|
| ||||
Can someone explain to me what the difference is between a storage class and a type is, with regards to const and invariant? For example, what do these do differently? invariant int foo; invariant(int) foo; ...? I know this is probably second-nature to people with C++ backgrounds, but I find the documentation quite confusing, as I've only really worked in Java before. |
June 18, 2007 Re: Difference betwee storage class and type (invariant/const)? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Robert Fraser | Robert Fraser wrote: > Can someone explain to me what the difference is between a storage class and a type is, with regards to const and invariant? For example, what do these do differently? > > invariant int foo; > invariant(int) foo; > > ...? I know this is probably second-nature to people with C++ backgrounds, but I find the documentation quite confusing, as I've only really worked in Java before. Between those? Nothing. The difference is here: invariant int* foo; invariant(int)* bar; The former is equivalent to: invariant(int*) foo; That is, when it is used as a storage class, it applies to the whole type. -- Kirk McDonald http://kirkmcdonald.blogspot.com Pyd: Connecting D and Python http://pyd.dsource.org |
June 18, 2007 Re: Difference betwee storage class and type (invariant/const)? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kirk McDonald | Ah, I see, thanks! So the difference is mainly when it applies to a naturally-reference type such as an object?
"const(Foo) bar" only the data inside the object is const, while with "const Foo bar", both the data and the reference are constant?
Kirk McDonald Wrote:
> Robert Fraser wrote:
> > Can someone explain to me what the difference is between a storage class and a type is, with regards to const and invariant? For example, what do these do differently?
> >
> > invariant int foo;
> > invariant(int) foo;
> >
> > ...? I know this is probably second-nature to people with C++ backgrounds, but I find the documentation quite confusing, as I've only really worked in Java before.
>
> Between those? Nothing. The difference is here:
>
> invariant int* foo;
> invariant(int)* bar;
>
> The former is equivalent to:
> invariant(int*) foo;
>
> That is, when it is used as a storage class, it applies to the whole type.
>
> --
> Kirk McDonald
> http://kirkmcdonald.blogspot.com
> Pyd: Connecting D and Python
> http://pyd.dsource.org
|
June 19, 2007 Re: Difference betwee storage class and type (invariant/const)? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Robert Fraser | > invariant int foo; This is like a compile-time constant invariant int foo = 1; foo = 2; // Fails: foo is not an lvalue auto fooptr = &foo; // Fails: 1 is not an lvalue > invariant(int) foo; This is something else and some of its behaviour I don't understand. invariant(int) foo = 1; // typeof(foo) seems to be int? foo = 2; // ok! auto fooptr = &foo; *fooptr = 3; // the docs say this should fail, but it compiles fine Note that invariant(int)* fooptr = &foo; fails with "cannot implicitly convert expression (& foo) of type int* to invariant(int)*", although the documentation says that should work. So making a type invariant seems to have no effect on plain data at the moment. It makes a difference for data containing references though: struct S { int x; int* p; } invariant(S) bar; bar.x = 1; // ok *bar.p = 1; // fails: not mutable auto barptr = &bar; //typeof(barptr) is invariant(S)* barptr.x = 2 // fails: not mutable Note also that static if(is(invariant(S*) == invariant(S)*)) does not pass, but invariant(S*) barptr2 = &bar; static if(is(typeof(barptr2) == invariant(S)*)) passes... is there a logical explanation for that? Cheers, Christian |
June 19, 2007 Re: Difference betwee storage class and type (invariant/const)? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Kirk McDonald | >> For example, what do these do differently?
>>
>> invariant int foo;
>> invariant(int) foo;
>
> Nothing.
I thought so too, but experimenting with the new compiler gives
void main()
{
invariant int foo;
invariant(int) bar;
static if(is(typeof(foo) == typeof(bar)))
pragma(msg, "Same types");
bar = 1;
foo = 1; // line 9
}
dmd invartest
Same types
invartest.d(9): Error: constant foo is not an lvalue
So... they are the same type but behave differently? Is that a bug?
Christian
|
June 19, 2007 Re: Difference betwee storage class and type (invariant/const)? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Robert Fraser | > For example, what do these do differently? > > invariant int foo; > invariant(int) foo; There is a big difference. invariant(int) foo; 1. the data of foo is an invariant int. 2. the brackets mean: you can assign another int to foo. You can't change the data of foo. But you are allowed to assign an other int to foo. So this doesn't make sense for a simple storage type like int. (for classes this is useful) invariant int foo; 1. the data of foo is an invariant int. 2. the reference of foo is invariant, too So you can't change the data of foo and you can't assign an other int to foo. And this makes sense ;) (for classes this isn't possible, since they can't be assigned at compile-time) If you want the same thing for a class, you have to write: final invariant(MyClass) foo = cast(invariant) new MyClass("mydata"); invariant(MyClass) foo; You can't change the data of foo (like: foo.x=10;). But you could assign an other MyClass to foo (like: foo = cast(invariant) new MyClass("an other MyClass");) final forbids the last step. It means that you can't assign an other MyClass to foo. This is equivalent: "final invariant(int)" and "invariant int". It also shows the need for having 3 different keywords. Even with explicit casting a class can't be assigned at compile-time: invariant MyClass foo = cast(invariant) new MyClass("data"); //Error: non-constant expression cast(invariant MyClass)new MyClass invariant(MyClass) foo = cast(invariant) new MyClass("data"); This is ok, but an other MyClass could be assigned to foo. So we mark it as final: final invariant(MyClass) foo = cast(invariant) new MyClass("data"); and get the same behavior as if we had: invariant MyClass foo = cast(invariant) new MyClass("data"); //Error: non-constant expression cast(invariant MyClass)new MyClass Just to mention it: const creates a read-only access to sth that might be mutable. invariant(MyClass*) ptr = ... //the data of MyClass will never ever change const(MyClass*) ptr = ... //you can't use ptr to change the data, ptr is pointing to Please correct me, if I was wrong with anything. Best regards, Daniel |
June 19, 2007 Re: Difference betwee storage class and type (invariant/const)? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Christian Kamm | Christian Kamm Wrote: [...] > struct S { int x; int* p; } > invariant(S) bar; > bar.x = 1; // ok > *bar.p = 1; // fails: not mutable Wait, so non-reference-types are mutable, but the data pointed to by reference types isn't...? Hwah...? I understand that structs are value types, but does this mean that the values within the struct can be changed while the values the struct points to can't be? And this differs from a class because a class is a reference type by default...? So, wait, struct Foo { int x; } class Bar { int x; } const(Foo) foo; const(Bar) bar = new Bar(); foo.x = 5; // Ok...? bar.x = 5; // Compile-time error...? Weird. I've always just used structs as stack-allocated classes without inheritence, constructors, or the overhead. Now there's another difference to worry about, I guess because they're value types... > static if(is(invariant(S*) == invariant(S)*)) > does not pass, but > invariant(S*) barptr2 = &bar; > static if(is(typeof(barptr2) == invariant(S)*)) > passes... is there a logical explanation for that? Now I'm even more confused... I'm from a Java background, so I don't really understand constness already, and the implementation here seems to be way weird... Anyways, thanks all... I guess I'll wait until the implementation matches the docs and there's a tutorial or something out there which explains this all without bringing up a lot of gray areas. |
June 20, 2007 Re: Difference betwee storage class and type (invariant/const)? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Robert Fraser | Robert Fraser wrote: > Christian Kamm Wrote: > > [...] > >> struct S { int x; int* p; } >> invariant(S) bar; >> bar.x = 1; // ok >> *bar.p = 1; // fails: not mutable > > Wait, so non-reference-types are mutable, but the data pointed to by reference types isn't...? Hwah...? I understand that structs are value types, but does this mean that the values within the struct can be changed while the values the struct points to can't be? And this differs from a class because a class is a reference type by default...? > > So, wait, > struct Foo { int x; } > class Bar { int x; } > const(Foo) foo; > const(Bar) bar = new Bar(); > foo.x = 5; // Ok...? > bar.x = 5; // Compile-time error...? > > Weird. I've always just used structs as stack-allocated classes without inheritence, constructors, or the overhead. Now there's another difference to worry about, I guess because they're value types... > >> static if(is(invariant(S*) == invariant(S)*)) >> does not pass, but >> invariant(S*) barptr2 = &bar; >> static if(is(typeof(barptr2) == invariant(S)*)) >> passes... is there a logical explanation for that? > > Now I'm even more confused... I'm from a Java background, so I don't really understand constness already, and the implementation here seems to be way weird... > > Anyways, thanks all... > I guess I'll wait until the implementation matches the docs and there's a tutorial or something out there which explains this all without bringing up a lot of gray areas. Does this help? It was written before the release of D 2.0, but it does try to explain the difference between the different kinds of const: http://while-nan.blogspot.com/2007/06/you-cant-touch-this.html As for the second thing, I'm not entirely sure either, but given that invariant(char)[] seems to have the behaviour one would expect from invariant(char[]), it could be that there's simply no difference and invariant(char)[] is the canonical form in the compiler. -- Daniel |
June 20, 2007 Re: Difference betwee storage class and type (invariant/const)? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Keep | Yup, that sort of makes sense, thanks.
Now I'm just wierded out by the whole thing where struct members can change value but things pointed to by the struct members can't. But I'll get used to it eventually. I think for the time being, I'll just put "in" on all my method signatures, remove it when the compiler complains, and not worry about the rest.
Daniel Keep Wrote:
>
>
> Robert Fraser wrote:
> > Christian Kamm Wrote:
> >
> > [...]
> >
> >> struct S { int x; int* p; }
> >> invariant(S) bar;
> >> bar.x = 1; // ok
> >> *bar.p = 1; // fails: not mutable
> >
> > Wait, so non-reference-types are mutable, but the data pointed to by reference types isn't...? Hwah...? I understand that structs are value types, but does this mean that the values within the struct can be changed while the values the struct points to can't be? And this differs from a class because a class is a reference type by default...?
> >
> > So, wait,
> > struct Foo { int x; }
> > class Bar { int x; }
> > const(Foo) foo;
> > const(Bar) bar = new Bar();
> > foo.x = 5; // Ok...?
> > bar.x = 5; // Compile-time error...?
> >
> > Weird. I've always just used structs as stack-allocated classes without inheritence, constructors, or the overhead. Now there's another difference to worry about, I guess because they're value types...
> >
> >> static if(is(invariant(S*) == invariant(S)*))
> >> does not pass, but
> >> invariant(S*) barptr2 = &bar;
> >> static if(is(typeof(barptr2) == invariant(S)*))
> >> passes... is there a logical explanation for that?
> >
> > Now I'm even more confused... I'm from a Java background, so I don't really understand constness already, and the implementation here seems to be way weird...
> >
> > Anyways, thanks all...
> > I guess I'll wait until the implementation matches the docs and there's a tutorial or something out there which explains this all without bringing up a lot of gray areas.
>
> Does this help? It was written before the release of D 2.0, but it does try to explain the difference between the different kinds of const: http://while-nan.blogspot.com/2007/06/you-cant-touch-this.html
>
> As for the second thing, I'm not entirely sure either, but given that
> invariant(char)[] seems to have the behaviour one would expect from
> invariant(char[]), it could be that there's simply no difference and
> invariant(char)[] is the canonical form in the compiler.
>
> -- Daniel
|
Copyright © 1999-2021 by the D Language Foundation