www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - const behaviour

reply "Namespace" <rswhite4 googlemail.com> writes:
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]
Jun 22 2012
next sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
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.
Jun 22 2012
parent Timon Gehr <timon.gehr gmx.ch> writes:
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.
Jun 22 2012
prev sibling next sibling parent "Namespace" <rswhite4 googlemail.com> writes:
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]
Jun 22 2012
prev sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
Jun 22 2012