digitalmars.D.learn - User defined types: Problems with ref
- Chris (25/25) Jan 23 2014 Here's what I'm trying to do.
- Chris (4/30) Jan 23 2014 Sorry in main it is:
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (34/73) Jan 23 2014 createElement does return a reference. However, because D does not have
- FreeSlave (11/37) Jan 23 2014 You can use pointer
Here's what I'm trying to do. struct Element(T) { T x; T y; public void setX(T value) { x = value; } // More fancy functions ... } I store Element(s) in an array and want to pass each one by reference, which does not work. class Tree { Element!string[] elements; public ref auto createElement(string name) { elements ~= Element!string(name); return elements[$-1]; } } in main: auto tag = Element!string("first"); The elements in Tree.elements and the ones in main are not the same, instead I obtain a copy of each. How can I make them refer to the same Elements? If I have to add a .ptr property to Element, how do I do that? Is that possible at all or did I shoot myself in the foot with the template?
Jan 23 2014
On Thursday, 23 January 2014 at 15:24:19 UTC, Chris wrote:Here's what I'm trying to do. struct Element(T) { T x; T y; public void setX(T value) { x = value; } // More fancy functions ... } I store Element(s) in an array and want to pass each one by reference, which does not work. class Tree { Element!string[] elements; public ref auto createElement(string name) { elements ~= Element!string(name); return elements[$-1]; } } in main: auto tag = Element!string("first"); The elements in Tree.elements and the ones in main are not the same, instead I obtain a copy of each. How can I make them refer to the same Elements? If I have to add a .ptr property to Element, how do I do that? Is that possible at all or did I shoot myself in the foot with the template?Sorry in main it is: auto tree = new Tree(); auto tag = tree.createElement("first");
Jan 23 2014
On 01/23/2014 07:26 AM, Chris wrote:On Thursday, 23 January 2014 at 15:24:19 UTC, Chris wrote:createElement does return a reference. However, because D does not have local references the type of tag is Element!string (not 'ref Element!string'). The following program demonstrates that the address of the returned reference is indeed the same as the one that has been created: import std.stdio; struct Element(T) { T x; T y; public void setX(T value) { x = value; } // More fancy functions ... } class Tree { Element!string[] elements; public ref auto createElement(string name) { elements ~= Element!string(name); writefln(" created element at %s", &elements[$-1]); return elements[$-1]; } } void main() { auto tree = new Tree(); writefln("received element at %s", &tree.createElement("first")); } Sample output: created element at 7F14C72C0F80 received element at 7F14C72C0F80 You can use the returned element directly as well: tree.createElement("second").setX("hello"); AliHere's what I'm trying to do. struct Element(T) { T x; T y; public void setX(T value) { x = value; } // More fancy functions ... } I store Element(s) in an array and want to pass each one by reference, which does not work. class Tree { Element!string[] elements; public ref auto createElement(string name) { elements ~= Element!string(name); return elements[$-1]; } } in main: auto tag = Element!string("first"); The elements in Tree.elements and the ones in main are not the same, instead I obtain a copy of each. How can I make them refer to the same Elements? If I have to add a .ptr property to Element, how do I do that? Is that possible at all or did I shoot myself in the foot with the template?Sorry in main it is: auto tree = new Tree(); auto tag = tree.createElement("first");
Jan 23 2014
On Friday, 24 January 2014 at 01:26:06 UTC, Ali Çehreli wrote:On 01/23/2014 07:26 AM, Chris wrote:Thank you guys. Yes, it's the array bit that kills the reference as FreeSlave pointed out. After tinkering around with it, I've (reluctantly) turned Element into a class to get the reference semantics. I need a reference so I can do things like tree.getElementById("div"); It's a basic (very simple) HTML / markup thing. Tree stores all elements, but the elements are changed outside Tree, like so auto div = tree.createElement("div"); div.setAttribute("id", "1"); // ... div.appendChild(...); etc. I'm sure there are cleverer ways of implementing a HTML tree.On Thursday, 23 January 2014 at 15:24:19 UTC, Chris wrote:reference,Here's what I'm trying to do. struct Element(T) { T x; T y; public void setX(T value) { x = value; } // More fancy functions ... } I store Element(s) in an array and want to pass each one bythe same,which does not work. class Tree { Element!string[] elements; public ref auto createElement(string name) { elements ~= Element!string(name); return elements[$-1]; } } in main: auto tag = Element!string("first"); The elements in Tree.elements and the ones in main are notadd ainstead I obtain a copy of each. How can I make them refer to the same Elements? If I have toat all or.ptr property to Element, how do I do that? Is that possiblecreateElement does return a reference. However, because D does not have local references the type of tag is Element!string (not 'ref Element!string'). The following program demonstrates that the address of the returned reference is indeed the same as the one that has been created: import std.stdio; struct Element(T) { T x; T y; public void setX(T value) { x = value; } // More fancy functions ... } class Tree { Element!string[] elements; public ref auto createElement(string name) { elements ~= Element!string(name); writefln(" created element at %s", &elements[$-1]); return elements[$-1]; } } void main() { auto tree = new Tree(); writefln("received element at %s", &tree.createElement("first")); } Sample output: created element at 7F14C72C0F80 received element at 7F14C72C0F80 You can use the returned element directly as well: tree.createElement("second").setX("hello"); Alidid I shoot myself in the foot with the template?Sorry in main it is: auto tree = new Tree(); auto tag = tree.createElement("first");
Jan 24 2014
Now the output is as it should be (after changing the elements). // The div.toString(); <div class="text" onclick="function();" id="1"> Hello, world! <span> I am a span </span> </div> // Tree Elements [<div class="text" onclick="function();" id="1"> Hello, world! <span> I am a span </span> </div> , <span> I am a span </span> ]
Jan 24 2014
On Thursday, 23 January 2014 at 15:24:19 UTC, Chris wrote:Here's what I'm trying to do. struct Element(T) { T x; T y; public void setX(T value) { x = value; } // More fancy functions ... } I store Element(s) in an array and want to pass each one by reference, which does not work. class Tree { Element!string[] elements; public ref auto createElement(string name) { elements ~= Element!string(name); return elements[$-1]; } } in main: auto tag = Element!string("first"); The elements in Tree.elements and the ones in main are not the same, instead I obtain a copy of each. How can I make them refer to the same Elements? If I have to add a .ptr property to Element, how do I do that? Is that possible at all or did I shoot myself in the foot with the template?You can use pointer Tree tree = new Tree(); Element!(string)* element = &tree.createElement("first"); & is to get address of returned value element. You also can rewrite your function like this: public Element!(string)* createElement(string name) { elements ~= Element!string(name); return &elements[$-1]; } to return pointer without need to get address on caller side.
Jan 23 2014
On Thursday, 23 January 2014 at 15:34:38 UTC, FreeSlave wrote:On Thursday, 23 January 2014 at 15:24:19 UTC, Chris wrote:Thanks, that was fast! Yes I was tinkering around with pointers, but didn't get it right, you did. However, the output is still the same, i.e. two different sets: // After creating and changing <div id="1"> Hello, world! <span> </span> </div> // The Elements in Tree.elements: [<div> </div> , <span> </span> ]Here's what I'm trying to do. struct Element(T) { T x; T y; public void setX(T value) { x = value; } // More fancy functions ... } I store Element(s) in an array and want to pass each one by reference, which does not work. class Tree { Element!string[] elements; public ref auto createElement(string name) { elements ~= Element!string(name); return elements[$-1]; } } in main: auto tag = Element!string("first"); The elements in Tree.elements and the ones in main are not the same, instead I obtain a copy of each. How can I make them refer to the same Elements? If I have to add a .ptr property to Element, how do I do that? Is that possible at all or did I shoot myself in the foot with the template?You can use pointer Tree tree = new Tree(); Element!(string)* element = &tree.createElement("first"); & is to get address of returned value element. You also can rewrite your function like this: public Element!(string)* createElement(string name) { elements ~= Element!string(name); return &elements[$-1]; } to return pointer without need to get address on caller side.
Jan 23 2014
On Thursday, 23 January 2014 at 15:24:19 UTC, Chris wrote:Thanks, that was fast! Yes I was tinkering around with pointers, but didn't get it right, you did. However, the output is still the same, i.e. two different sets: // After creating and changing <div id="1"> Hello, world! <span> </span> </div> // The Elements in Tree.elements: [<div> </div> , <span> </span> ]Maybe more code will explain more. Note that array requires data to be continuous, so if there are no space for new element, it reallocates the whole chunk and therefore invalidates old pointers. Use linked list or replace struct with class.
Jan 23 2014
Anyway, why do you need pointers to elements?
Jan 23 2014