August 16, 2012
Something I'm having trouble undertanding/remembering (sorry, you've probaby already explained it a billion times)...

I remember being told many times that D's 'const' provides stronger guarantees than C++'s 'const'.

I just wanted to clarify, is that true for 'const' itself, or is that referring only to when 'const' is used with other D-specific features (immutable, etc.)?

If it's the former, is there some example piece of code in each language, for comparison, that shows how the compiler can infer more from D's const than C++'s?

If so, it might be worth posting something like that on the website.
August 16, 2012
> I remember being told many times that D's 'const' provides stronger guarantees than C++'s 'const'.


I also remember being told that the compiler considers it UB to cast away const-ness in references, unlike in C++, which gives you more guarantees.

But I'm having trouble coming up with a pieces of source code that illustrate the issue.
August 16, 2012
On Thursday, 16 August 2012 at 22:14:31 UTC, Mehrdad wrote:
> Something I'm having trouble undertanding/remembering (sorry, you've probaby already explained it a billion times)...
>
> I remember being told many times that D's 'const' provides stronger guarantees than C++'s 'const'.

> If it's the former, is there some example piece of code in each language, for comparison, that shows how the compiler can infer more from D's const than C++'s?

Note that stronger guarentees does not translate to inferences done by the compiler.

> If so, it might be worth posting something like that on the website.

I believe there is an article which speaks to const, but the inference benefits come from immutability and pure functions. The const page does have a comparison table at the end:

http://dlang.org/const3.html

The main thing given is transitivity. The compiler will guarantee you aren't changing data that is const.

On the note of casting away const, I don't believe that is the operation which is undefined, however modifying const is undefined as it could be pointing to immutable data.
August 16, 2012
On Thursday, 16 August 2012 at 23:18:08 UTC, Jesse Phillips wrote:
> Note that stronger guarentees does not translate to inferences done by the compiler.

I remember being told (correct me if I'm wrong) that D's const lets the compiler perform better optimizations than C++, which i.e. means the compiler can infer more about the source code.


> The const page does have a comparison table at the end:
>
> http://dlang.org/const3.html

That just tells you how to use const, not why it's useful compared to C++.


> The main thing given is transitivity.

Sure, but what kind of an advantage does that provide compared to C++?
(As in, a code sample would be awesome -- it's so much easier to explain with an example to compare, rather than with words.)


> The compiler will guarantee you aren't changing data that is const.

Right, but it's the same with C++, right? Where's the difference?



> On the note of casting away const, I don't believe that is the operation which is undefined, however modifying const is undefined as it could be pointing to immutable data.

Oh, then that's not what I'd understood. Seems just like C++ then.



> I believe there is an article which speaks to const, but the inference benefits come from immutability and pure functions.

Ahh, right. You need immutability and purity for const to be any more advantageous than in C++. It seems like it's a point worth emphasizing in the const article (and perhaps when explaining const to newbies), since people might not understand why const is powerful unless they actually start using immutability, too.
(Also kind of prevents the situation where C++ users try to use const as logical const, without realizing that it's meant to work with immutability/purity instead.)
August 17, 2012
On Friday, August 17, 2012 01:35:46 Mehrdad wrote:
> > The main thing given is transitivity.
> 
> Sure, but what kind of an advantage does that provide compared to
> C++?
> (As in, a code sample would be awesome -- it's so much easier to
> explain with an example to compare, rather than with words.)

In C++, if you have

const vector<T*>& getStuff() const;

which returns a member variable, then as long as const isn't cast away, you know that the container itself won't have any elements added or removed from it, but you have _zero_ guarantees about the elements themselves. In contrast, in D,

const ref Array!(T*) getStuff() const;

you would _know_ that not only is the container not altered, but you know that the elements aren't altered either - or anything which the elements point to. And since casting away const and mutating a variable is undefined behavior, and there is no mutable, you don't have to worry about the state of the object changing at all unless it's shared (since another thread could alter it through a non-const reference) or you can somehow get another, non-const reference to it in the current thread. So, it becomes trivial for a class or struct to guarantee that nothing can change the member variables that it returns from const functions.

> > The compiler will guarantee you aren't changing data that is const.
> 
> Right, but it's the same with C++, right? Where's the difference?

C++ makes no such guarantees, because you're free to cast away const and modifiy objects and because objects can have members marked with the mutable keyword. All const really does in C++ is make it so that you don't accidentally, directly modify a variable which is const. It makes _zero_ guarantees about the state of the object beyond that.

> > On the note of casting away const, I don't believe that is the operation which is undefined, however modifying const is undefined as it could be pointing to immutable data.
> 
> Oh, then that's not what I'd understood. Seems just like C++ then.

No. Casting away const and modifying an object is well-defined in C++. The casting is well-defined in D but not the modification. That's undefined behavior - both because it will do nasty things if the object is actually immutable and because D allows the compiler to assume that anything which is const is not modified by another thread if it's not shared (the _only_ thing which could alter that variable is another, mutable reference to the same data on the same thread).

> > I believe there is an article which speaks to const, but the inference benefits come from immutability and pure functions.
> 
> Ahh, right. You need immutability and purity for const to be any more advantageous than in C++. It seems like it's a point worth emphasizing in the const article (and perhaps when explaining const to newbies), since people might not understand why const is powerful unless they actually start using immutability, too. (Also kind of prevents the situation where C++ users try to use const as logical const, without realizing that it's meant to work with immutability/purity instead.)

const is useful even without purity, because you _know_ that nothing which is const can change unless you access it through a non-const reference, and everything being thread-local by default makes it that much harder for that to happen, allowing the compiler to more easily guarantee that a const object isn't changed and do optimizations based on that.

Now, it _does_ get far better once purity is added into the mix, because then neither you or the compiler has to worry about function calls altering a variable through global variables, since they can't be accessed, making it easier for you to understand the code and easier for the compiler to make optimizations. But D's const by itself still allows for more optimizations than C++'s const does.

And of course, immutable offers even better guarantees, since neither you nor the compiler has to worry about there being mutable references to the same data anywhere. So, it enables even better optimizations (and combined with pure, it can even lead to whole function calls being elided).

While D's const can be too restrictive at times, I'm increasingly annoyed by how flimsy C++'s const is in comparison. In particular, without transitivity, putting const on a getter frequently means next to nothing.

- Jonathan M Davis
August 17, 2012
Mehrdad:

>> On the note of casting away const, I don't believe that is the operation which is undefined, however modifying const is undefined as it could be pointing to immutable data.
>
> Oh, then that's not what I'd understood. Seems just like C++ then.

Are you sure?

bye,
bearophile
August 17, 2012
On Friday, 17 August 2012 at 00:10:52 UTC, Jonathan M Davis wrote:
> In C++, if you have
>
> const vector<T*>& getStuff() const;
>
> which returns a member variable, then as long as const isn't cast away, you know that the container itself won't have any elements added or removed from it, but you have _zero_ guarantees about the elements themselves.

Right.


> In contrast, in D,
>
> const ref Array!(T*) getStuff() const;
>
> you would _know_ that not only is the container not altered,
> but you know that the elements aren't altered either -
> or anything which the elements point to.


I'm not so sure about that.

int yourGlobalCounter;

struct MyIntPtrArray
{
	int*[] items;

	MyIntPtrArray()
	{
		items = new int*[1];
		items[0] = &yourGlobalField;
	}

	ref const(int*[]) getItems() const
	{
		++yourGlobalCounter;
		return items;
	}
}


> And since casting away const and mutating a variable is undefined behavior,

That is either vague, or contradicts what I was told above.
We all know casting away a const _object_ is undefined behavior in both D and C++.
However, is casting away a const __reference__ undefined behavior in D? (It's not in C++.)


>> > The compiler will guarantee you aren't changing data that is const.
>> 
>> Right, but it's the same with C++, right? Where's the difference?
>
> C++ makes no such guarantees, because you're free to cast away const and modifiy objects


Not correct, as far as I understand.
C++ only lets you cast away _const references_ to _mutable_ objects.
If the object happens to have been const _itself_, then that's undefined behavior.


> and because objects can have members marked with the mutable keyword.

Right, it's the equivalent of static fields, see my example above.





>> > On the note of casting away const, I don't believe that is the operation which is undefined, however modifying const is undefined as it could be pointing to immutable data.
>> Oh, then that's not what I'd understood. Seems just like C++ then.
>
> No. Casting away const and modifying an object is well-defined in C++.


Only if the object was mutable to begin with. See above.





> const is useful even without purity, because you _know_ that nothing which is const can change unless you access it through a non-const reference


Yeah, and as I just showed, aliasing messes this up just as badly as in C++. See above.


> Now, it _does_ get far better once purity is added into the mix
> And of course, immutable offers even better guarantees

Yup, I agree about those; I'm just referring to const here.
August 17, 2012
On Friday, 17 August 2012 at 00:32:03 UTC, Mehrdad wrote:
> Not correct, as far as I understand.
> C++ only lets you cast away _const references_ to _mutable_ objects.
> If the object happens to have been const _itself_, then that's undefined behavior.


Er, minor correction:

By "casting away const"  I mean  "casting away const and actually mutating the object through the new, unconst reference". Obviously, I'm not referring to the mere cast itself, which doesn't do anything unless used for something else.
August 17, 2012
On Friday, 17 August 2012 at 00:13:58 UTC, bearophile wrote:
> Mehrdad:
>
>>> On the note of casting away const, I don't believe that is the operation which is undefined, however modifying const is undefined as it could be pointing to immutable data.
>>
>> Oh, then that's not what I'd understood. Seems just like C++ then.
>
> Are you sure?


Yes, I'm pretty sure that something like

	const int x = 5;
	int* p = const_cast<int*>(&x);
	*p = 6;

is undefined behavior, because x is a const object.

However,

	int y = 5;
	const int& x = y;
	int* p = const_cast<int*>(&x);
	*p = 6;

is well-defined, because the object is mutable.



At least, that's my understanding of C++; feel free to correct me if I'm wrong.
August 17, 2012
On Friday, August 17, 2012 02:32:01 Mehrdad wrote:
> > C++ makes no such guarantees, because you're free to cast away const and modifiy objects
> 
> Not correct, as far as I understand.
> C++ only lets you cast away _const references_ to _mutable_
> objects.
> If the object happens to have been const _itself_, then that's
> undefined behavior.

Well, then our understandings on the matter conflict, and I don't know for certain which of us is correct.

- Jonathan M Davis
« First   ‹ Prev
1 2 3 4 5 6 7 8
Top | Discussion index | About this forum | D home