www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - What is the difference between...

reply "Janice Caron" <caron serenityfirefly.com> writes:
What is the difference between:

 int f(const void * p, int len)

and

 int f(const(void)* p, int len)

?
Sep 07 2007
next sibling parent reply Xinok <xnknet gmail.com> writes:
const void*
This can also be read as:
const(void*)
This means that both 'void' and the pointer are const.

const(void)*
The pointer is mutable, but the data it points to must be const, even 
though it doesn't know the type of the data.

Janice Caron wrote:
 What is the difference between:
 
 int f(const void * p, int len)
 
 and
 
 int f(const(void)* p, int len)
 
 ?
 
Sep 07 2007
parent torhu <no spam.invalid> writes:
Xinok wrote:
 const void*
 This can also be read as:
 const(void*)
 This means that both 'void' and the pointer are const.
'const(void*)' is the same as 'const(void)*'. The reason is explained here: http://www.digitalmars.com/d/final-const-invariant.html Scroll down to "Invariant Doesn't Apply To Declared Symbols".
Sep 07 2007
prev sibling next sibling parent Derek Parnell <derek psych.ward> writes:
On Fri, 7 Sep 2007 10:54:25 +0100, Janice Caron wrote:

 What is the difference between:
 
  int f(const void * p, int len)
Can't change 'p'
 
  int f(const(void)* p, int len)
Can't change that which 'p' points to. (I think ...) -- Derek Parnell Melbourne, Australia skype: derek.j.parnell
Sep 07 2007
prev sibling next sibling parent "Janice Caron" <caron serenityfirefly.com> writes:
OK. Not quite what I was getting at, but still useful, thanks.

In that case, what is the difference between:

 int f(const void * p, int len)

and

 int f(const(void *) p, int len)

?

Put another way: what's the difference between "const (...)" with brackets and 
"const ..." without? What happens when you take the brackets away? What is the 
difference between const as a parameter storage class, and const as a type 
modifier?



The following really does compile without error:

 void f(const const(int) p)

and I don't understand what the two different versions of "const" are each 
doing.




-----Original Message-----
From: digitalmars-d-bounces puremagic.com 
[mailto:digitalmars-d-bounces puremagic.com] On Behalf Of Xinok
Sent: 07 September 2007 11:08
To: digitalmars-d puremagic.com
Subject: Re: What is the difference between...

 const void*
 This can also be read as:
 const(void*)
 This means that both 'void' and the pointer are const.

 const(void)*
 The pointer is mutable, but the data it points to must be const, even though 
 it doesn't know the type of the data.

 Janice Caron wrote:
 What is the difference between:

 int f(const void * p, int len)

 and

 int f(const(void)* p, int len)

 ?
Sep 07 2007
prev sibling next sibling parent reply "Janice Caron" <caron serenityfirefly.com> writes:
Even more simply put, what is the difference between:

(1) void f(const int x)
(2) void f(const(int) x)
(3) void f(const const(int) x)

Just trying to get my head around this!
Sep 07 2007
next sibling parent Daniel919 <Daniel919 web.de> writes:
Janice Caron schrieb:
 Even more simply put, what is the difference between:
 
 (1) void f(const int x)
You can't assign an other int to x.
 (2) void f(const(int) x)
Useless, like all: const/invariant(simplestoragetype)
 (3) void f(const const(int) x)
Just like (1)
Sep 07 2007
prev sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
IIRC...

Janice Caron wrote:
 Even more simply put, what is the difference between:
 
 (1) void f(const int x)
That's const as a storage class: the bits of 'x' are immutable.
 (2) void f(const(int) x)
const as a type constructor: in this case, nothing happens since const(T) only has an effect on reference types. Let's change it to
 (2) void f(const(int*) x)
Ok, now you've got a mutable read-only view: the bits of 'x' can be changed, but the data referenced by x cannot.
 (3) void f(const const(int) x)
*rubs out previous line*
 (3) void f(const const(int*) x)
I suspect the const(int*) is redundant. Since const is transitive, const as a storage class automatically applies const-ness to the type as well.
 Just trying to get my head around this!
-- Daniel
Sep 07 2007
parent reply Sean Kelly <sean f4.ca> writes:
Daniel Keep wrote:
 
 (2) void f(const(int*) x)
Ok, now you've got a mutable read-only view: the bits of 'x' can be changed, but the data referenced by x cannot.
I thought that's what 'final' was for. For the above, I'd expect the reference and the data to which it refers to both be immutable through x. Is this not right? Sean
Sep 07 2007
parent reply Sean Kelly <sean f4.ca> writes:
Sean Kelly wrote:
 Daniel Keep wrote:
 (2) void f(const(int*) x)
Ok, now you've got a mutable read-only view: the bits of 'x' can be changed, but the data referenced by x cannot.
I thought that's what 'final' was for. For the above, I'd expect the reference and the data to which it refers to both be immutable through x. Is this not right?
er, let me clarify. I would assume that: const(int)* x means that the data cannot be changed but the pointer can. But by enclosing the pointer in parens, it should be considered constant as well. Sean
Sep 07 2007
parent Sean Kelly <sean f4.ca> writes:
Sean Kelly wrote:
 Sean Kelly wrote:
 Daniel Keep wrote:
 (2) void f(const(int*) x)
Ok, now you've got a mutable read-only view: the bits of 'x' can be changed, but the data referenced by x cannot.
I thought that's what 'final' was for. For the above, I'd expect the reference and the data to which it refers to both be immutable through x. Is this not right?
er, let me clarify. I would assume that: const(int)* x means that the data cannot be changed but the pointer can. But by enclosing the pointer in parens, it should be considered constant as well.
Forget it, I remember now. The parenthesis means "apply this attribute to the type herein" and const means "can't change the data." Out of curiosity, how do things work with multiple attributes: final const(int*)* x const final(int*)* x I assume that both of the above are equivalent, and they mean "mutable pointer to an immutable pointer to immutable data." ie. all of the attributes together apply to the type in parens. Is this correct? I'll admit I still find the C++ version easier to visually parse for non-trivial declarations--the rule is simply "apply this attribute to the adjacent thing on the left." But perhaps this is because I've spent more time with C++ const than D const. Sean
Sep 07 2007
prev sibling next sibling parent reply "Janice Caron" <caron serenityfirefly.com> writes:
-----Original Message-----
From: digitalmars-d-bounces puremagic.com 
[mailto:digitalmars-d-bounces puremagic.com] On Behalf Of Daniel919
Sent: 07 September 2007 12:39
To: digitalmars-d puremagic.com
Subject: Re: What is the difference between...

 (2) void f(const(int) x)
Useless, like all: const/invariant(simplestoragetype)
It is? Why? Why doesn't it mean x is a const int? So f(const(int)* x) means x is a pointer to const int, but f(const(int) x) does not mean x is a const int? Now I'm very, very confused. Why am I not getting this?
Sep 07 2007
parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Janice Caron wrote:
 -----Original Message-----
 From: digitalmars-d-bounces puremagic.com 
 [mailto:digitalmars-d-bounces puremagic.com] On Behalf Of Daniel919
 Sent: 07 September 2007 12:39
 To: digitalmars-d puremagic.com
 Subject: Re: What is the difference between...
 
 (2) void f(const(int) x)
Useless, like all: const/invariant(simplestoragetype)
It is? Why? Why doesn't it mean x is a const int? So f(const(int)* x) means x is a pointer to const int, but f(const(int) x) does not mean x is a const int? Now I'm very, very confused. Why am I not getting this?
const(...) makes everything inside the parenthesis const. But there is one exception: If that const is part of a declaration, then the top-level value/type is not const. (the top-level value is the one that changes with assignments) So: const(int)* x; // mutable pointer to const int const(int) x; // mutable int; const(int*) x; // mutable pointer to const int const(int**) x; // mutable pointer to const pointer to const int; const(int*)* x; // mutable pointer to const pointer to const int; const(int)** x; // mutable pointer to mutable pointer to const int; The only way to apply const to the toplevel value, is to use const as a "storage class" (crappy name). So: const int* x; // const pointer to const int BTW, your posts are not getting threading right, could you check your client? -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 07 2007
parent reply Sean Kelly <sean f4.ca> writes:
Bruno Medeiros wrote:
 Janice Caron wrote:
 -----Original Message-----
 From: digitalmars-d-bounces puremagic.com 
 [mailto:digitalmars-d-bounces puremagic.com] On Behalf Of Daniel919
 Sent: 07 September 2007 12:39
 To: digitalmars-d puremagic.com
 Subject: Re: What is the difference between...

 (2) void f(const(int) x)
Useless, like all: const/invariant(simplestoragetype)
It is? Why? Why doesn't it mean x is a const int? So f(const(int)* x) means x is a pointer to const int, but f(const(int) x) does not mean x is a const int? Now I'm very, very confused. Why am I not getting this?
const(...) makes everything inside the parenthesis const. But there is one exception: If that const is part of a declaration, then the top-level value/type is not const. (the top-level value is the one that changes with assignments) So: const(int)* x; // mutable pointer to const int const(int) x; // mutable int; const(int*) x; // mutable pointer to const int const(int**) x; // mutable pointer to const pointer to const int; const(int*)* x; // mutable pointer to const pointer to const int;
Wouldn't this be "mutable pointer to mutable pointer to const int?" Sean
Sep 07 2007
parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Sean Kelly wrote:
 Bruno Medeiros wrote:
 Janice Caron wrote:
 -----Original Message-----
 From: digitalmars-d-bounces puremagic.com 
 [mailto:digitalmars-d-bounces puremagic.com] On Behalf Of Daniel919
 Sent: 07 September 2007 12:39
 To: digitalmars-d puremagic.com
 Subject: Re: What is the difference between...

 (2) void f(const(int) x)
Useless, like all: const/invariant(simplestoragetype)
It is? Why? Why doesn't it mean x is a const int? So f(const(int)* x) means x is a pointer to const int, but f(const(int) x) does not mean x is a const int? Now I'm very, very confused. Why am I not getting this?
const(...) makes everything inside the parenthesis const. But there is one exception: If that const is part of a declaration, then the top-level value/type is not const. (the top-level value is the one that changes with assignments) So: const(int)* x; // mutable pointer to const int const(int) x; // mutable int; const(int*) x; // mutable pointer to const int const(int**) x; // mutable pointer to const pointer to const int; const(int*)* x; // mutable pointer to const pointer to const int;
Wouldn't this be "mutable pointer to mutable pointer to const int?" Sean
The last one : const(int*)* x; ? Nope, it's like I said. It can be verified with this: x = null; // Ok *x = null; // Error **x = null; // Error If people were thinking that const(<X>) would *allways* only apply immutability to the referenced value of <X> (if X is a reference), then that's wrong. It only does that when const(<X>) is the top-level type. (BTW, naturally, the same is true for invariant) -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 07 2007
parent reply Sean Kelly <sean f4.ca> writes:
Bruno Medeiros wrote:
 Sean Kelly wrote:
 Bruno Medeiros wrote:
 Janice Caron wrote:
 -----Original Message-----
 From: digitalmars-d-bounces puremagic.com 
 [mailto:digitalmars-d-bounces puremagic.com] On Behalf Of Daniel919
 Sent: 07 September 2007 12:39
 To: digitalmars-d puremagic.com
 Subject: Re: What is the difference between...

 (2) void f(const(int) x)
Useless, like all: const/invariant(simplestoragetype)
It is? Why? Why doesn't it mean x is a const int? So f(const(int)* x) means x is a pointer to const int, but f(const(int) x) does not mean x is a const int? Now I'm very, very confused. Why am I not getting this?
const(...) makes everything inside the parenthesis const. But there is one exception: If that const is part of a declaration, then the top-level value/type is not const. (the top-level value is the one that changes with assignments) So: const(int)* x; // mutable pointer to const int const(int) x; // mutable int; const(int*) x; // mutable pointer to const int const(int**) x; // mutable pointer to const pointer to const int; const(int*)* x; // mutable pointer to const pointer to const int;
Wouldn't this be "mutable pointer to mutable pointer to const int?" Sean
The last one : const(int*)* x; ? Nope, it's like I said.
So the "top-level value/type" rule you mention above applies to the entire type rather than just the bit in parenthesis? Then there is effectively no difference between "const(int**) x" and "const(int*)*" correct? So why are both syntaxes accepted? Sean
Sep 07 2007
parent reply Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Sean Kelly wrote:
 Bruno Medeiros wrote:
 Sean Kelly wrote:
 Bruno Medeiros wrote:
 Janice Caron wrote:
 -----Original Message-----
 From: digitalmars-d-bounces puremagic.com 
 [mailto:digitalmars-d-bounces puremagic.com] On Behalf Of Daniel919
 Sent: 07 September 2007 12:39
 To: digitalmars-d puremagic.com
 Subject: Re: What is the difference between...

 (2) void f(const(int) x)
Useless, like all: const/invariant(simplestoragetype)
It is? Why? Why doesn't it mean x is a const int? So f(const(int)* x) means x is a pointer to const int, but f(const(int) x) does not mean x is a const int? Now I'm very, very confused. Why am I not getting this?
const(...) makes everything inside the parenthesis const. But there is one exception: If that const is part of a declaration, then the top-level value/type is not const. (the top-level value is the one that changes with assignments) So: const(int)* x; // mutable pointer to const int const(int) x; // mutable int; const(int*) x; // mutable pointer to const int const(int**) x; // mutable pointer to const pointer to const int; const(int*)* x; // mutable pointer to const pointer to const int;
Wouldn't this be "mutable pointer to mutable pointer to const int?" Sean
The last one : const(int*)* x; ? Nope, it's like I said.
So the "top-level value/type" rule you mention above applies to the entire type rather than just the bit in parenthesis?
Yes, if by "entire type" we mean the type of a declarations (and of typeofs too).
 Then there is 
 effectively no difference between "const(int**) x" and "const(int*)*" 
 correct? 
Nope.
 So why are both syntaxes accepted?
 
 
 Sean
I would *guess* it's so you have a way to declare a mutable class (reference) that refers to immutable class data. I.e.: const(Foo) foo; then 'foo = xpto' is allowed, but 'foo.x = xpto' is not. If const(<X>) were to work without that exception rule, then there would be no way to declare something like the above. For pointers you could do: const(int)* x; but for classes, there would be no syntax. But one would have to ask Walter to know for sure. Was any of this discussed at the conference? This 'head'/'tail' Robert has been mentioned seems related. Seems the term 'head' is the same as 'top-level value'. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 07 2007
parent reply Nathan Reed <nathaniel.reed gmail.com> writes:
Bruno Medeiros wrote:
 This 'head'/'tail' Robert 
 has been mentioned seems related. Seems the term 'head' is the same as 
 'top-level value'.
 
Yes. The 'final' storage class makes the head const, which as you've pointed out can't be done with the 'const' type constructor. So: const(int)* x; // mutable pointer to const int const(int*) x; // mutable pointer to const int final const(int)* x; // const pointer to const int final const(int*) x; // const pointer to const int (This is described on the lecture slides from the conference, so I'm not sure if it is implemented quite this way yet.) However, there is also still the 'const' storage class (as distinct from the type constructor)...it's not clear to me exactly how that differs. Does anyone else think this is much too confusing? I realize D const is a different animal from C++ const, but it seems to be badly in need of some simplification. Thanks, Nathan Reed
Sep 07 2007
next sibling parent Sean Kelly <sean f4.ca> writes:
Nathan Reed wrote:
 Bruno Medeiros wrote:
 This 'head'/'tail' Robert has been mentioned seems related. Seems the 
 term 'head' is the same as 'top-level value'.
Yes. The 'final' storage class makes the head const, which as you've pointed out can't be done with the 'const' type constructor. So: const(int)* x; // mutable pointer to const int const(int*) x; // mutable pointer to const int final const(int)* x; // const pointer to const int final const(int*) x; // const pointer to const int (This is described on the lecture slides from the conference, so I'm not sure if it is implemented quite this way yet.) However, there is also still the 'const' storage class (as distinct from the type constructor)...it's not clear to me exactly how that differs.
The 'const' storage class is essentially the same as 'const' works in D 1.0 now. The advantage being that the compiler can place the data in ROM or simply use them as compile-time constants and not store them at all.
 Does anyone else think this is much too confusing?  I realize D const is 
 a different animal from C++ const, but it seems to be badly in need of 
 some simplification.
I do. In fact, as much as I hate to say it, I actually find the C++ declarative form easier to visually parse. The new head/tail idea for D 2.0 is better than what we have now however, and I think we can do better still (though I don't have any suggestions yet regarding how). Sean
Sep 08 2007
prev sibling parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Nathan Reed wrote:
 
 Does anyone else think this is much too confusing?  I realize D const is 
 a different animal from C++ const, but it seems to be badly in need of 
 some simplification.
 
 Thanks,
 Nathan Reed
Yes, I also think it's very confusing, and it's not the only aspect of the syntax I don't like, but what can we do... -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 08 2007
prev sibling parent reply "Janice Caron" <caron serenityfirefly.com> writes:
-----Original Message-----
From: digitalmars-d-bounces puremagic.com 
[mailto:digitalmars-d-bounces puremagic.com] On Behalf Of Daniel Keep
Sent: 07 September 2007 12:58
To: digitalmars-d puremagic.com
Subject: Re: What is the difference between...

 const(T) only has an effect on reference types.
O-Kaaaay. Forgive me, but, that seems arbitrary and ... silly. If const(T) worked on all types, we'd have no need for const T, surely? So, let's see if I've understood this right. Given struct S { int x; } /* a non-reference type */ class C { int x; } /* a reference type */ void f(const(S) s, const(C) c) { s.x = 5; /* allowed */ c.x = 5; /* not allowed */ } Is that really, really right? It's going to take me a long time before that seems intuitive!
Sep 07 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Janice Caron wrote:
 -----Original Message-----
 From: digitalmars-d-bounces puremagic.com
 [mailto:digitalmars-d-bounces puremagic.com] On Behalf Of Daniel Keep
 Sent: 07 September 2007 12:58
 To: digitalmars-d puremagic.com
 Subject: Re: What is the difference between...
 
 const(T) only has an effect on reference types.
O-Kaaaay. Forgive me, but, that seems arbitrary and ... silly. If const(T) worked on all types, we'd have no need for const T, surely? So, let's see if I've understood this right. Given struct S { int x; } /* a non-reference type */ class C { int x; } /* a reference type */ void f(const(S) s, const(C) c) { s.x = 5; /* allowed */ c.x = 5; /* not allowed */ } Is that really, really right? It's going to take me a long time before that seems intuitive!
I get the feeling you haven't read the various articles on how const works in D 2.0... D 2.0 adds, basically, five kinds of const. 1. "final" (storage class) -- makes a variable's bits immutable after the relevant constructor has finished (so this() for classes, static this() for modules) or immediately after it's been assigned to. Does not produce a literal constant in ROM. 2. "const" (storage class) -- makes a variable's bits immutable at compile time, and transitively adds const(T) to the stored type. 3. "invariant" (storage class) -- makes a variable's bits immutable at compile time, and transitively adds invariant(T) to the stored type. 4. "const(T)" (type constructor) -- turns any reference type T into a read-only view of the referenced data; has no effect on non-reference types. 5. "invariant(T)" (type constructor) -- turns any reference type T into a *globally immutable* view of the referenced data. This means that not only can't you make changes, no one else can, either. Has no effect on non-reference types. What you have to realise is that D 2.0's const system is *NOT* the same as C's, C++'s, D 1.0's or anyone else's. Yes, it's weird when you first see it, but there are good reasons for it being the way it is. Here's some links: * http://www.digitalmars.com/d/const.html * http://while-nan.blogspot.com/2007/06/you-cant-touch-this.html (note: this was written before D 2.0 was released and doesn't contain the storage class versions of "const" and "invariant", but should otherwise be correct). -- Daniel
Sep 07 2007
parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Daniel Keep wrote:
 
 
 4. "const(T)" (type constructor) -- turns any reference type T into a
 read-only view of the referenced data; has no effect on non-reference types.
 
 5. "invariant(T)" (type constructor) -- turns any reference type T into
 a *globally immutable* view of the referenced data.  This means that not
 only can't you make changes, no one else can, either.  Has no effect on
 non-reference types.
 
That's not quite the case, see my previous post. -- Bruno Medeiros - MSc in CS/E student http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 07 2007