www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Insert array into an AA

reply nrgyzer <nrgyzer gmail.com> writes:
Hi everyone,

I've the following:

private static ubyte[][2][hash_t] classInstances;

this() {

   classInstances[toHash()] = new ubyte[2]; // does not work

}

I want insert every class instance into the hashmap. Every class
instance should be contained in the map after the constructor was
called. When I compile my code, I get "Error: cannot implicitly
convert expression (new ubyte[](2u)) of type ubyte[] to ubyte[][]"
which is logical. But is there any way to insert every instance into
the array and define the array/map for this entry?

Thanks in advance!
Aug 16 2011
next sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 16 Aug 2011 15:17:33 -0400, nrgyzer <nrgyzer gmail.com> wrote:

 Hi everyone,

 I've the following:

 private static ubyte[][2][hash_t] classInstances;

 this() {

    classInstances[toHash()] = new ubyte[2]; // does not work

 }

 I want insert every class instance into the hashmap. Every class
 instance should be contained in the map after the constructor was
 called. When I compile my code, I get "Error: cannot implicitly
 convert expression (new ubyte[](2u)) of type ubyte[] to ubyte[][]"
 which is logical. But is there any way to insert every instance into
 the array and define the array/map for this entry?

It's inadvisable to do this, unless you plan on manually deleting the instances. The reason is because the hash will maintain a pointer to every class instance, which means the GC will never collect them. Also, it's hard to know why you selected that type, but changing classInstances to ubyte[][hash_t] should work. Also, you don't need hash_t, you should be able to do ubyte[][Object] classInstances. then add like: classInstances[this] = new ubyte[2]; The call to toHash is implicit. -Steve
Aug 16 2011
prev sibling parent reply Robert Clipsham <robert octarineparrot.com> writes:
On 16/08/2011 20:17, nrgyzer wrote:
 Hi everyone,

 I've the following:

 private static ubyte[][2][hash_t] classInstances;

 this() {

     classInstances[toHash()] = new ubyte[2]; // does not work

 }

 I want insert every class instance into the hashmap. Every class
 instance should be contained in the map after the constructor was
 called. When I compile my code, I get "Error: cannot implicitly
 convert expression (new ubyte[](2u)) of type ubyte[] to ubyte[][]"
 which is logical. But is there any way to insert every instance into
 the array and define the array/map for this entry?

 Thanks in advance!

Is there any particular reason you're using ubyte[][2][hash_t] there? To keep a reference to each instance simply use: ---- class MyClass { static MyClass[] classInstances; this() { classInstances ~= this; } } ---- If you in fact want to have a hashmap indexed by the instances with values of type ubyte[][2], you can do this: ---- class MyClass { static ubyte[][2][MyClass] classInstances; this() { classInstances[this] = new ubyte[][2]; } } ---- The problem in your original code is that you were using = new ubyte[2] rather than = new ubyte[][2]. Hope this helps. -- Robert http://octarineparrot.com/
Aug 16 2011
next sibling parent reply nrgyzer <nrgyzer gmail.com> writes:
== Auszug aus Robert Clipsham (robert octarineparrot.com)'s Artikel
 On 16/08/2011 20:17, nrgyzer wrote:
 Hi everyone,

 I've the following:

 private static ubyte[][2][hash_t] classInstances;

 this() {

     classInstances[toHash()] = new ubyte[2]; // does not work

 }

 I want insert every class instance into the hashmap. Every class
 instance should be contained in the map after the constructor was
 called. When I compile my code, I get "Error: cannot implicitly
 convert expression (new ubyte[](2u)) of type ubyte[] to ubyte[][]"
 which is logical. But is there any way to insert every instance into
 the array and define the array/map for this entry?

 Thanks in advance!

keep a reference to each instance simply use: ---- class MyClass { static MyClass[] classInstances; this() { classInstances ~= this; } } ---- If you in fact want to have a hashmap indexed by the instances with values of type ubyte[][2], you can do this: ---- class MyClass { static ubyte[][2][MyClass] classInstances; this() { classInstances[this] = new ubyte[][2]; } } ---- The problem in your original code is that you were using = new ubyte[2] rather than = new ubyte[][2]. Hope this helps.

Ok, that works - thx. Steve: I'll delete the entries from the map, but what's about overriding the toHash()-function and return a simply int value? I also need this map-structure for further steps in my application. I's possible to change it to ubyte[][hash_t] classInstancesOne; // or ubyte[][MyClass] ubyte[][hash_t] classInstancesTwo; // or ubyte[][MyClass] but I thought one map for the same sense is better. Btw: I've two classes where one inherits: class MyClassOne { protected { static __gshared { uint counter; uint[MyClassOne] fixedData; } uint otherData; this(uint d) { otherData = d; } } this() { fixedData[this] = ++counter; } property ref { uint myPropOne() { return fixedData[this]; } uint myPropTwo() { return otherData; } } } class MyClassTwo : MyClassOne { shared(MyClassOne) supInstance; this(uint d, MyClassOne mco) { super(d); supInstance = mco; } override ref alias supInstance.myPropOne myPropOne; } When I create an instance of MyClassOne and call myPropOne on it, I get "1". When I'm using this instance to create an instance of MyClassTwo and call myPropOne, I get "0". Is there anything I'm doing wrong? What I'm trying to do is: One super-class which contains some fixed data (not inheritable) and some data which are different for each class.
Aug 18 2011
parent nrgyzer <nrgyzer gmail.com> writes:
== Auszug aus Steven Schveighoffer (schveiguy yahoo.com)'s Artikel
 On Thu, 18 Aug 2011 06:47:32 -0400, nrgyzer <nrgyzer gmail.com>

 == Auszug aus Robert Clipsham (robert octarineparrot.com)'s


 On 16/08/2011 20:17, nrgyzer wrote:
 Hi everyone,

 I've the following:

 private static ubyte[][2][hash_t] classInstances;

 this() {

     classInstances[toHash()] = new ubyte[2]; // does not work

 }

 I want insert every class instance into the hashmap. Every




 instance should be contained in the map after the constructor




 called. When I compile my code, I get "Error: cannot implicitly
 convert expression (new ubyte[](2u)) of type ubyte[] to ubyte[]




 which is logical. But is there any way to insert every




 the array and define the array/map for this entry?

 Thanks in advance!




 keep a reference to each instance simply use:
 ----
 class MyClass {
      static MyClass[] classInstances;
      this() {
          classInstances ~= this;
      }
 }
 ----
 If you in fact want to have a hashmap indexed by the instances



 values of type ubyte[][2], you can do this:
 ----
 class MyClass {
      static ubyte[][2][MyClass] classInstances;
      this() {
          classInstances[this] = new ubyte[][2];
      }
 }
 ----
 The problem in your original code is that you were using = new



 rather than = new ubyte[][2]. Hope this helps.

Ok, that works - thx. Steve: I'll delete the entries from the map, but what's about overriding the toHash()-function and return a simply int value?


 maybe not for your context), then a collision occurs.  Then opCmp

 to determine if they are actually identical.
 If you use hash_t as your key, then only one object is stored in

 the other is simply overwritten.
 I also need this map-structure for further steps in my


 possible to change it to

 ubyte[][hash_t] classInstancesOne; // or ubyte[][MyClass]
 ubyte[][hash_t] classInstancesTwo; // or ubyte[][MyClass]

 but I thought one map for the same sense is better.

 Btw: I've two classes where one inherits:

 class MyClassOne {

    protected {
       static __gshared {
          uint counter;
          uint[MyClassOne] fixedData;
       }
       uint otherData;

       this(uint d) {
          otherData = d;
       }
    }

    this() {
       fixedData[this] = ++counter;
    }

     property ref {
       uint myPropOne() { return fixedData[this]; }
       uint myPropTwo() { return otherData; }
    }

 }

 class MyClassTwo : MyClassOne {

    shared(MyClassOne) supInstance;

    this(uint d, MyClassOne mco) {
       super(d);
       supInstance = mco;
    }

    override ref alias supInstance.myPropOne myPropOne;

 }

 When I create an instance of MyClassOne and call myPropOne on it,


 "1". When I'm using this instance to create an instance of
 MyClassTwo and call myPropOne, I get "0". Is there anything I'm


 wrong?

there. For sure, override ref is not needed. I'm surprised all of this compiles.
 What I'm trying to do is: One super-class which contains some


 (not inheritable) and some data which are different for each
 class.

Also note that even though you've only created one instance of

 every MyClassTwo instance is a MyClassOne (and calls MyClassOne's
 constructor).  I think you have applied the wrong techniques to

 your design.  Without knowing further your design/context, I can't

 help.
 -Steve

I'm working on a game where the player can build different buildings. There are some general building-structures which defines the costs to build it and some other things, but the name of each building can be modified by the player. So, each building can have it's own name, but the costs to build are always the same for each building. To prevent the redefinition of all the property-methods, I want redirect the properties of a simple building-property to it's building structure. For example: class BuildingShell { private float[BuildingShell] pCostsToBuild; protected { string pName; this(string name) { pName = name; } } this(string name, float costs) { pName = name; pCostsToBuild[this] = costs; } property { ref float costsToBuild() { return pCostsToBuild[this]; } string name() { return pName; } } } class Building : BuildingShell { shared(BuildingShell) pShell; this(BuldingShell bs, string name) { super(name); pShell = cast(shared) bs; } override property pShell.costsToBuild costsToBuild; } All instances of BuildingShell will be loaded from a stream, so I need the ref-keyword in the properties. Because of multi-threading I also need a shared BuildingShell in the Building-class.
Aug 19 2011
prev sibling parent "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Thu, 18 Aug 2011 06:47:32 -0400, nrgyzer <nrgyzer gmail.com> wrote:

 == Auszug aus Robert Clipsham (robert octarineparrot.com)'s Artikel
 On 16/08/2011 20:17, nrgyzer wrote:
 Hi everyone,

 I've the following:

 private static ubyte[][2][hash_t] classInstances;

 this() {

     classInstances[toHash()] = new ubyte[2]; // does not work

 }

 I want insert every class instance into the hashmap. Every class
 instance should be contained in the map after the constructor was
 called. When I compile my code, I get "Error: cannot implicitly
 convert expression (new ubyte[](2u)) of type ubyte[] to ubyte[][]"
 which is logical. But is there any way to insert every instance into
 the array and define the array/map for this entry?

 Thanks in advance!

keep a reference to each instance simply use: ---- class MyClass { static MyClass[] classInstances; this() { classInstances ~= this; } } ---- If you in fact want to have a hashmap indexed by the instances with values of type ubyte[][2], you can do this: ---- class MyClass { static ubyte[][2][MyClass] classInstances; this() { classInstances[this] = new ubyte[][2]; } } ---- The problem in your original code is that you were using = new ubyte[2] rather than = new ubyte[][2]. Hope this helps.

Ok, that works - thx. Steve: I'll delete the entries from the map, but what's about overriding the toHash()-function and return a simply int value?

If two instances return the same hash value (as is easily possible, but maybe not for your context), then a collision occurs. Then opCmp is used to determine if they are actually identical. If you use hash_t as your key, then only one object is stored in the map, the other is simply overwritten.
 I also need this map-structure for further steps in my application. I's  
 possible to change it to

 ubyte[][hash_t] classInstancesOne; // or ubyte[][MyClass]
 ubyte[][hash_t] classInstancesTwo; // or ubyte[][MyClass]

 but I thought one map for the same sense is better.

ubyte[][Object] should work for all class types.
 Btw: I've two classes where one inherits:

 class MyClassOne {

    protected {
       static __gshared {
          uint counter;
          uint[MyClassOne] fixedData;
       }
       uint otherData;

       this(uint d) {
          otherData = d;
       }
    }

    this() {
       fixedData[this] = ++counter;
    }

     property ref {
       uint myPropOne() { return fixedData[this]; }
       uint myPropTwo() { return otherData; }
    }

 }

 class MyClassTwo : MyClassOne {

    shared(MyClassOne) supInstance;

    this(uint d, MyClassOne mco) {
       super(d);
       supInstance = mco;
    }

    override ref alias supInstance.myPropOne myPropOne;

 }

 When I create an instance of MyClassOne and call myPropOne on it, I get  
 "1". When I'm using this instance to create an instance of
 MyClassTwo and call myPropOne, I get "0". Is there anything I'm doing  
 wrong?

That crazy override ref alias line, I have no idea what you're doing there. For sure, override ref is not needed. I'm surprised all of this compiles.
 What I'm trying to do is: One super-class which contains some fixed data  
 (not inheritable) and some data which are different for each
 class.

Note that protected does not prevent MyClassTwo from changing it. Also note that even though you've only created one instance of MyClassOne, every MyClassTwo instance is a MyClassOne (and calls MyClassOne's constructor). I think you have applied the wrong techniques to solving your design. Without knowing further your design/context, I can't really help. -Steve
Aug 19 2011