Thread overview
const behaviour
Jun 22, 2012
Namespace
Jun 22, 2012
Timon Gehr
Jun 22, 2012
Namespace
Jun 22, 2012
Timon Gehr
Jun 22, 2012
Ali Çehreli
June 22, 2012
Based to the current const discussions (once again) I wanted to appease my curiosity and want to ask why the following code works as described in the comments:

[code]

import std.stdio;

class Bar { }

class Foo {
private:
	string _text;
	
	Bar _b;
	
public:
	this(string text, Bar b) {
		this._text = text;
		this._b = b;
	}
	
	// const_behaviour.d(18): Error: cannot implicitly convert expression (this._b) of type const(Bar) to const_behaviour.Bar
	Bar GetB() const pure nothrow { /// <- must be const(Bar) instead of Bar
		return this._b;
	}
	
	string GetText() const pure nothrow { /// <- no const(string) is neccessary. Why?
		return this._text;
	}
}

void main() {
	Bar b = new Bar();
	
	Foo f = new Foo("foobar", b);
}

[/code]
June 22, 2012
On 06/22/2012 11:21 AM, Namespace wrote:
> Based to the current const discussions (once again) I wanted to appease
> my curiosity and want to ask why the following code works as described
> in the comments:
>
> [code]
>
> import std.stdio;
>
> class Bar { }
>
> class Foo {
> private:
>      string _text;
>
>      Bar _b;
>
> public:
>      this(string text, Bar b) {
>          this._text = text;
>          this._b = b;
>      }
>
>      // const_behaviour.d(18): Error: cannot implicitly convert
> expression (this._b) of type const(Bar) to const_behaviour.Bar
>      Bar GetB() const pure nothrow { /// <- must be const(Bar) instead
> of Bar
>          return this._b;
>      }
>
>      string GetText() const pure nothrow { /// <- no const(string) is
> neccessary. Why?
>          return this._text;
>      }
> }
>
> void main() {
>      Bar b = new Bar();
>
>      Foo f = new Foo("foobar", b);
> }
>
> [/code]

string is immutable(char)[] and const(immutable(char)[]) implicitly
converts to immutable(char)[]. Or put differently, a string doesn't
have to be const-qualified because it cannot be changed anyway.
June 22, 2012
As far as i know "int" is not immutable or const by default.
So, why work this code:

[code]
import std.stdio;

class Bar {
	
}

class Foo {
private:
	int _id;
	
	Bar _b;
	
public:
	this(int id, Bar b) {
		this._id = id;
		
		this._b = b;
	}
	
	// const_behaviour.d(18): Error: cannot implicitly convert expression (this._b) of type const(Bar) to const_behaviour.Bar
	const(Bar) GetB() const pure nothrow { /// <- must be const(Bar) instead of Bar
		return this._b;
	}
	
	int GetId() const pure nothrow { /// <- no const(int) is neccessary. Why?!
		return this._id;
	}
}

void main() {
	Bar b = new Bar();
	
	Foo f = new Foo(42, b);
}
[/code]
June 22, 2012
On 06/22/2012 12:25 PM, Namespace wrote:
> As far as i know "int" is not immutable or const by default.
> So, why work this code:
>
> [code]
> import std.stdio;
>
> class Bar {
>
> }
>
> class Foo {
> private:
>      int _id;
>
>      Bar _b;
>
> public:
>      this(int id, Bar b) {
>          this._id = id;
>
>          this._b = b;
>      }
>
>      // const_behaviour.d(18): Error: cannot implicitly convert
> expression (this._b) of type const(Bar) to const_behaviour.Bar
>      const(Bar) GetB() const pure nothrow { /// <- must be const(Bar)
> instead of Bar
>          return this._b;
>      }
>
>      int GetId() const pure nothrow { /// <- no const(int) is
> neccessary. Why?!
>          return this._id;
>      }
> }
>
> void main() {
>      Bar b = new Bar();
>
>      Foo f = new Foo(42, b);
> }
> [/code]

The same reason, because const(int) implicitly converts to int. If the
data is copied, the qualifiers can be changed in any way that is
desired. As string, int has no mutable indirections.
June 22, 2012
On 06/22/2012 02:21 AM, Namespace wrote:
> Based to the current const discussions (once again) I wanted to appease
> my curiosity and want to ask why the following code works as described
> in the comments:
>
> [code]
>
> import std.stdio;
>
> class Bar { }
>
> class Foo {
> private:
> string _text;

_text is a reference to immutable(char).

>
> Bar _b;

_b is a reference to mutable Bar.

>
> public:
> this(string text, Bar b) {
> this._text = text;
> this._b = b;
> }
>
> // const_behaviour.d(18): Error: cannot implicitly convert expression
> (this._b) of type const(Bar) to const_behaviour.Bar
> Bar GetB() const pure nothrow {

That function promises that the object will not be modified through it.

>  /// <- must be const(Bar) instead of Bar

That is not entirely correct. The return type need not be const(Bar). The problem is with what you are returning.

> return this._b;

That is the problem. To enforce its no-mutation guarantee, the function cannot return a non-const reference to the Bar object that _b is a reference of. The return type Bar compiles with this code:

    Bar GetB() const pure nothrow {
        return new Bar();
    }

> }
>
> string GetText() const pure nothrow { /// <- no const(string) is
> neccessary. Why?

Because _text is a non-mutating reference.

> return this._text;
> }
> }
>
> void main() {
> Bar b = new Bar();
>
> Foo f = new Foo("foobar", b);
> }
>
> [/code]

Note that the caller can modify the string that GetText() returns by e.g. appending to it:

    string t = f.GetText();

t is a copy of _text. They currently share the same characters: "foobar".

    t ~= "zar";

The act of appending does not change _text in any way. It still refers to "foobar".

Ali

-- 
D Programming Language Tutorial: http://ddili.org/ders/d.en/index.html