www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - D1 and read-only views?

reply "Nick Sabalausky" <a a.a> writes:
Am I correct in my understanding of the following regarding D1?:

Suppose there's a D1 class like this:

class Foo
{
  // Johnny Coder wants the string to be readable from
  // outside Foo, but not changable from outside Foo.
  // He handles it as he would an int:

  private char[] _myStr;
  public char[] myStr()
  {
    return _myStr;
  }

  this()
  {
    // Have to awkwardly .dup this in case Foo
    // itself wants to modify _myStr in-place.
    _myStr = "bar".dup;
  }
}

That contains a bug (in "myStr()") because myStr() simply returns a pointer 
(and length, of course) to the actual data, and the caller could use that to 
change the data:

auto f = new Foo();
auto str = f.myStr();
assert(f.myStr() == "bar"); // Ok
str[0] = 'c';
assert(f.myStr() == "bar"); // FAIL!

Unlike C and D2, D1's const doesn't create a read-only view, but simply 
means the value is set at compile-time. D1 doesn't have anything else 
comparable to the C or D2 const so if Johnny Coder wants to make his 
interface to Foo safe, his only choice is to make myStr() duplicate the 
string:

  public char[] myStr()
  {
    return _myStr.dup;
  }

Is this all correct?

(Note, I'm not complaining about any of this, I realize it's all been 
improved in D2. Just making sure I understand the D1 version correctly.) 
Apr 10 2009
next sibling parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Fri, Apr 10, 2009 at 1:21 PM, Nick Sabalausky <a a.a> wrote:
 Am I correct in my understanding of the following regarding D1?:

 Suppose there's a D1 class like this:

 class Foo
 {
 =A0// Johnny Coder wants the string to be readable from
 =A0// outside Foo, but not changable from outside Foo.
 =A0// He handles it as he would an int:

 =A0private char[] _myStr;
 =A0public char[] myStr()
 =A0{
 =A0 =A0return _myStr;
 =A0}

 =A0this()
 =A0{
 =A0 =A0// Have to awkwardly .dup this in case Foo
 =A0 =A0// itself wants to modify _myStr in-place.
 =A0 =A0_myStr =3D "bar".dup;
 =A0}
 }

 That contains a bug (in "myStr()") because myStr() simply returns a point=
er
 (and length, of course) to the actual data, and the caller could use that=
to
 change the data:

 auto f =3D new Foo();
 auto str =3D f.myStr();
 assert(f.myStr() =3D=3D "bar"); // Ok
 str[0] =3D 'c';
 assert(f.myStr() =3D=3D "bar"); // FAIL!

 Unlike C and D2, D1's const doesn't create a read-only view, but simply
 means the value is set at compile-time. D1 doesn't have anything else
 comparable to the C or D2 const so if Johnny Coder wants to make his
 interface to Foo safe, his only choice is to make myStr() duplicate the
 string:

 =A0public char[] myStr()
 =A0{
 =A0 =A0return _myStr.dup;
 =A0}

 Is this all correct?
Yes.
Apr 10 2009
prev sibling next sibling parent Kagamin <spam here.lot> writes:
You can also create an indexer. As it's done in .net
Apr 11 2009
prev sibling parent Daniel Keep <daniel.keep.lists gmail.com> writes:
As others have stated, your surmise is correct.

On a related note, I recently wrote a very simple cstring struct that
acts like const(char)[] does in D2.  I was using unique interned
strings, and didn't want any surprises.  You can still get a mutable
reference to the string by using .toString, but the struct is really
only there to prevent accidental modifications.

  -- Daniel
Apr 12 2009