January 24, 2007
Walter Bright wrote:
> 1) there are *legal* ways to subvert it,

You mean, const_cast<> and other casts? If so, this is no reason to say D shouldn't have similar implementation. You can implement it in D but without allowing any way of removing const-ness from the object reference. I never used const_cast<> or any other way of removing const-ness from an object in 8 years of C++ coding.

If you mean subverting it by changing the object by its original reference, or by a different non-const reference, this is another problem, that doesn't invalidate const itself. Const applies to a specific reference to an object, not the object itself.

If you mean by using mutables, I see no problem here also. Mutable is not meant to be used for any attribute, just for caches and other specific attributes that doesn't affect the object real state.

If you are afraid of programmers misusing const, by subverting it... well... programmers also misuse operator overload, templates, delegates, etc... what doesn't make these features wrong.

> meaning it is useless as a semantic aid

No, it is not. const is a contract that says that the function will not change the object, at least not through *that specific reference*. This does not mean that the object won't be changed during the function call.

> and useless to the optimizer/code generator

No solution will ever be useful to the optimizer or the code generator. There is no way to guarantee that the state of any referenced object will be constant, unless you kill thread support and restrict so much what a function can do that it becomes an annoyance. Anyway, const doesn't mean optimization, it is just a form of contract.

By the way, are you aware of the new 'restrict' keyword of C99? It addresses exactly the optimization facet that 'const' doesn't; for function parameters only.

> 2) it confuses a type modifier with a storage class (exhibiting muddled
> special case behaviors)

Does it? I think this is an implementation issue.

I think that in a good const implementation (not exactly compatible with C++) the const variant of a type should be the same as the non-const variant, just with a special "property" that restricts access, and not a completely different type.

This means that

	class X {
		X func(Y a);
		const X func(const Y a) const;
	};

would generate a compile-time error, since both member functions are identical once you make const a reference property, and not a different type.

> 3) it's ugly and litters declarations

Sorry, but it is your personal opinion. This doesn't make const bad.

> 4) the use of overloading based on const is a workaround to another design flaw in C++

If you mean like the above case, yeah, sure. This does not mean that this problem have no solution. I foresee a very simple solution like the covariant return type already implemented in D. It is not that difficult.

There are three cases for returning const types:
  (1) the member function should always return a const reference,
  (2) the member function should always return a non-const reference
(like a copy operator), and
  (3) the member function should return a self-reference, respecting the
const-ness of the object reference it was called from.

For (1), we may declare:

	class X {
		const X getConstInstanceOfX();
				// always returns a const instance, to
				// self or to something else
	}

For (2):

	class X {
		X copy();	// always returns a new, non-const
				// instance of X
	}

For (3), we would need another new keyword or mechanism to mean "conditional constness depending on 'this'". Some suggestions are 'volatile const', or 'scope const' (overloading some already-existing keywords), or something like 'condconst', or something else.

	class X {
		condconst X opCall() const;
				// returns a self-reference, function
				// shouldn't modify object since it may
				// be called as const
	}

So, any case in which in C++ you would write a pair of identical functions overloaded by const, you would use this third case in D.
January 24, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> Chris Nicholson-Sauls wrote:
>> So then I ask, why have const constructors/destructors?  What, given an (even contrived) example, would be the likely difference in code between constant and non-constant constructors/destructors?  And how is this:
> 
> A constructor might take different decisions on caching, preallocating
> etc. when it prepares for mutability, as opposed to it knowing that the
> object won't change. For example, creating a const deque might cause a different allocation strategy than a non-const one.
> 
>> # Foo f = new const Foo;
>>
>> Different from this: # const Foo f = new Foo;
> 
> In the latter case you are robbing the constructor from a little piece of information. Things will still work.
> 
> 
> Andrei

I was about to ask the same that Chris N.S. did. So how about a destructor, what would a const destructor differ from a normal one? Perhaps to destroy the const object in cases where such object was created in such a way that the normal destructor no longer correctly knows how to destroy the const object? Seems reasonable but I can't think of an example of the top of my head.

-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
January 24, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> 
> * D avoids the issue of duplicated function bodies in the following way:
> 
> struct Widget
> {
>   storageof(this) int* Foo(storageof(this))(int i) { ... }
> }
> 

Hum... what if I want to override such functions? Will D even allow it?

-- 
Bruno Medeiros - MSc in CS/E student
http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
January 24, 2007
Bruno Medeiros wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>>
>> * D avoids the issue of duplicated function bodies in the following way:
>>
>> struct Widget
>> {
>>   storageof(this) int* Foo(storageof(this))(int i) { ... }
>> }
>>
> 
> Hum... what if I want to override such functions? Will D even allow it?

Technically that's a template function, so you can't override it. But it's a template with only a few specializations, so in theory overriding could be made to work.

Andrei
January 24, 2007
Bruno Medeiros wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> Chris Nicholson-Sauls wrote:
>>> So then I ask, why have const constructors/destructors?  What, given an (even contrived) example, would be the likely difference in code between constant and non-constant constructors/destructors?  And how is this:
>>
>> A constructor might take different decisions on caching, preallocating
>> etc. when it prepares for mutability, as opposed to it knowing that the
>> object won't change. For example, creating a const deque might cause a different allocation strategy than a non-const one.
>>
>>> # Foo f = new const Foo;
>>>
>>> Different from this: # const Foo f = new Foo;
>>
>> In the latter case you are robbing the constructor from a little piece of information. Things will still work.
>>
>>
>> Andrei
> 
> I was about to ask the same that Chris N.S. did. So how about a destructor, what would a const destructor differ from a normal one? Perhaps to destroy the const object in cases where such object was created in such a way that the normal destructor no longer correctly knows how to destroy the const object? Seems reasonable but I can't think of an example of the top of my head.

If a const constructor does things a different way than the non-const constructor, it follows that the const destructor might need to "undo" things differently too. E.g., a const constructor can use sharing among all const instances. Consequently, the const destructor must know this so it doesn't assume it owns the object's resources.

Andrei
January 24, 2007
Miles wrote:
> Walter Bright wrote:
[snip]
>> 2) it confuses a type modifier with a storage class (exhibiting muddled
>> special case behaviors)
> 
> Does it? I think this is an implementation issue.

Wrong. It is a definitional issue that confuses even experts.

> I think that in a good const implementation (not exactly compatible with
> C++) the const variant of a type should be the same as the non-const
> variant, just with a special "property" that restricts access, and not a
> completely different type.
> 
> This means that
> 
> 	class X {
> 		X func(Y a);
> 		const X func(const Y a) const;
> 	};
> 
> would generate a compile-time error, since both member functions are
> identical once you make const a reference property, and not a different
> type.

That's pretty limiting; you can't define something a la STL begin() that returns different objects depending on the object's mutability.

>> 3) it's ugly and litters declarations
> 
> Sorry, but it is your personal opinion. This doesn't make const bad.

Littering declarations is objective. In C++ const is never deduced, only checked. The underlying vision is that there should be cases in which constness is deduced such that programmers can benefit of it without having to babysit the compiler.

>> 4) the use of overloading based on const is a workaround to another
>> design flaw in C++
> 
> If you mean like the above case, yeah, sure. This does not mean that
> this problem have no solution. I foresee a very simple solution like the
> covariant return type already implemented in D. It is not that difficult.
> 
> There are three cases for returning const types:
>   (1) the member function should always return a const reference,
>   (2) the member function should always return a non-const reference
> (like a copy operator), and
>   (3) the member function should return a self-reference, respecting the
> const-ness of the object reference it was called from.

Sorry, this is simplistic and incomplete. A member function might want to return whatever, including two unrelated types depending on constness.


Andrei
January 24, 2007
Rioshin an'Harthen wrote:

> "Kyle Furlong" <kylefurlong@gmail.com> wrote:
>> Ah the great const debate. I have a feeling that this discussion will be a major part of D 2.0.
> 
> I wish we'd gone the const by default way before releasing 1.0, no matter how much code would've been broken... It's so much harder now to get something as good into the language, as it's more likely that production code is being written with D, and we have to think of backwards compatibility. That wasn't much of an issue before.

This is true, by offputting this particular discussion for a resolution, the breaking when it is finally fixed will be much greater, whereas the current problematic behaviour will frustrate more than it did (after all, the D user mass seems to grow), possibly making the next round of discussions even harder to follow.

-- 
Lars Ivar Igesund
blog at http://larsivi.net
DSource & #D: larsivi
Dancing the Tango
January 24, 2007
Lars Ivar Igesund wrote:

> Rioshin an'Harthen wrote:
> 
>> "Kyle Furlong" <kylefurlong@gmail.com> wrote:
>>> Ah the great const debate. I have a feeling that this discussion will be a major part of D 2.0.
>> 
>> I wish we'd gone the const by default way before releasing 1.0, no matter how much code would've been broken... It's so much harder now to get something as good into the language, as it's more likely that production code is being written with D, and we have to think of backwards compatibility. That wasn't much of an issue before.
> 
> This is true, by offputting this particular discussion for a resolution, the breaking when it is finally fixed will be much greater, whereas the current problematic behaviour will frustrate more than it did (after all, the D user mass seems to grow), possibly making the next round of discussions even harder to follow.
> 

I suppose I should read the _whole_ thread prior to posting such opinions, but it was so darned long! Going through all of it, it seems like we may gain a proper resolution soonish, which will be better than even later :)

-- 
Lars Ivar Igesund
blog at http://larsivi.net
DSource & #D: larsivi
Dancing the Tango
January 24, 2007
Andrei Alexandrescu (See Website For Email) wrote:
> That's pretty limiting; you can't define something a la STL begin() that returns different objects depending on the object's mutability.

This is almost prejudice against const. You broke my message in this point just to argue against it, without considering the explanation that follows.

If you think just a little about the solution, you will see that the solution cames immediately. iterator<> and const_iterator<> will became the exact same class, with no distinction between const and non-const.

> Littering declarations is objective. In C++ const is never deduced, only checked. The underlying vision is that there should be cases in which constness is deduced such that programmers can benefit of it without having to babysit the compiler.

I don't share your vision. Doesn't make any sense the compiler deduce const.

So I write a get() method that should only return a value from the object, but I inadvertently replace a == with a =, or something alike, and the compiler deduces this is a non-const method, instead of failing to compile it. So wrong...

A const member function is not "babysitting" the compiler, it is the way the programmer have to tell the compiler that that function is not intended to modify the object, so the compiler can aid disallowing any operation that would affect the object state. Also, it is a documentation tool.

> Sorry, this is simplistic and incomplete.
> A member function might want to return whatever,

If the same named member function should return different objects, then you should seriously think renaming them to different names, since they don't do the same thing.

> including two unrelated types depending on constness.

The only reason I see for returning two "unrelated" (?) types depending on constness is in situations like STL begin(), and in this specific situation, there is simply no reason for having two different types like iterator<> and const_iterator<>. If you have read my message, this would have came immediately. The conditional const I proposed aids just this.
January 24, 2007
Miles wrote:
> Andrei Alexandrescu (See Website For Email) wrote:
>> That's pretty limiting; you can't define something a la STL begin() that
>> returns different objects depending on the object's mutability.
> 
> This is almost prejudice against const. You broke my message in this
> point just to argue against it, without considering the explanation that
> follows.
> 
> If you think just a little about the solution, you will see that the
> solution cames immediately. iterator<> and const_iterator<> will became
> the exact same class, with no distinction between const and non-const.

I broke the message because it was long, having some content that I agree with (as in "true but uninteresting"). If you get to work out on an actual design for your idea, you will just see how it does not work.

>> Littering declarations is objective. In C++ const is never deduced, only
>> checked. The underlying vision is that there should be cases in which
>> constness is deduced such that programmers can benefit of it without
>> having to babysit the compiler.
> 
> I don't share your vision. Doesn't make any sense the compiler deduce const.

Well this is simply wrong, and fortunately there's no need for an explanation because there is plenty of previous work on qualifier inference (http://www.cs.umd.edu/~jfoster/papers/pldi99.pdf and Faehndrich follow-up work). Walter and I already discussed a number of workable instances of const deduction.


Andrei
1 2 3 4 5 6 7 8 9 10
Next ›   Last »