View mode: basic / threaded / horizontal-split · Log in · Help
June 22, 2012
const behaviour
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
Re: const behaviour
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
Re: const behaviour
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
Re: const behaviour
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
Re: const behaviour
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
Top | Discussion index | About this forum | D home