digitalmars.D.learn - Dynamically Sized Structs
- Jeroen Bollen (16/16) Apr 16 2014 Is it possible to have a structure with a dynamic size? The
- Justin Whear (34/52) Apr 16 2014 No, you can't make the structs dynamic. I had a similar situation
- bearophile (7/8) Apr 16 2014 See an usage example I have written here:
- Dicebot (6/14) Apr 16 2014 Just in case, the key line to pay attention to in that example is
- monarch_dodra (10/15) Apr 16 2014 Absolutely. However, from a technical point of view, it doesn't
- bearophile (11/16) Apr 17 2014 When you define dynamically sized structs it's also a good idea
- Kagamin (2/2) Apr 17 2014 Bound checked version of variable size struct:
- Kagamin (2/4) Apr 17 2014 Well, indexes getter could take cellCount into account...
- bearophile (6/8) Apr 17 2014 I think you are missing one of the main points of a variable
- Dicebot (2/10) Apr 17 2014 Yeah, otherwise one could have just used dynamic array field.
- Kagamin (3/11) Apr 17 2014 As far as I can see, my implementation has only 1 indirection
- Dicebot (2/16) Apr 17 2014 And C-like dynamic structs have 0 indirection.
- Kagamin (1/1) Apr 17 2014 State* pointer in sokoban example is a perfect 1 indirection.
- Dicebot (16/17) Apr 17 2014 It is not related to actual "dynamic struct" thing, which is why
- Kagamin (1/1) Apr 17 2014 How is this different from my example?
- Dicebot (3/4) Apr 17 2014 b = new byte[StateImpl.sizeof + CellIndex.sizeof*cellCount];
- Kagamin (5/5) Apr 17 2014 So you assert that variable length structs can't be allocated on
- John Colvin (2/4) Apr 17 2014 Locality. The stack is (within reason) readily available in cache.
- Kagamin (6/6) Apr 17 2014 Well, cache locality can be optimized without reducing number of
- Steven Schveighoffer (4/8) Apr 17 2014 I think the biggest issue I would have with your implementation would be...
- Kagamin (2/2) Apr 17 2014 Well, it's proof of concept of bound checked variable-size
- Steven Schveighoffer (7/9) Apr 18 2014 Please take no offense :) I just was pointing out a difference between a...
- Kagamin (3/3) Apr 18 2014 I mean, it doesn't cover all scenarios, but can be extended to
- Kagamin (3/3) Apr 18 2014 Oh, and I don't believe, that a variable-size struct can be
- Steven Schveighoffer (4/7) Apr 18 2014 It goes at the end. Then you need to allocate the whole thing with that ...
- Kagamin (9/12) Apr 18 2014 Speaking about mixin magic, you probably suggest to do it overly
- John Colvin (7/24) Apr 17 2014 Well, technically everything on the stack is accessed through an
- Kagamin (14/18) Apr 17 2014 This can illustrate
- Rene Zwanenburg (6/22) Apr 16 2014 Dynamic structs are impossible with D's static type system.
Is it possible to have a structure with a dynamic size? The structure would contain an array. I know I can use templates, but the size won't be known at compile time. I also know I could just put a dynamic array into it, but that way it would just be a pointer. I know there would be major issues like how to pass the struct to a function, as it has an unknown size, but to be quite honest I just want pretty code. I'm doing network related operations. I was hoping there'd still be a way to do this using templates or so? I just don't want to go through the hassle of writing a constructor for it to fill in all the fields, and a toByteArray method to convert it back to raw data. struct MyStruct { ulong length; ubyte[length] data; // obv won't compile }
Apr 16 2014
On Wed, 16 Apr 2014 23:15:40 +0000, Jeroen Bollen wrote:Is it possible to have a structure with a dynamic size? The structure would contain an array. I know I can use templates, but the size won't be known at compile time. I also know I could just put a dynamic array into it, but that way it would just be a pointer. I know there would be major issues like how to pass the struct to a function, as it has an unknown size, but to be quite honest I just want pretty code. I'm doing network related operations. I was hoping there'd still be a way to do this using templates or so? I just don't want to go through the hassle of writing a constructor for it to fill in all the fields, and a toByteArray method to convert it back to raw data. struct MyStruct { ulong length; ubyte[length] data; // obv won't compile }No, you can't make the structs dynamic. I had a similar situation reading shapefiles a while ago and approached it like this: struct lengthOf { string fieldName; } struct Polygon { ulong numParts; lengthOf("numParts") Part[] parts; ulong numPoints; lengthOf("numPoints") Point[] points; } T read(T)(...) if (/** T is one of your wire-format structs **/) { T ret; foreach (I, field; ret.tupleof) { static if (isDynamicArray!(typeof(field))) { // use __traits(getAttributes) on the field to get the lengthOf attribute // mixin a line like this: mixin(`field.length = ret.`~lengthOf.fieldName~`;`); rawRead(field); } else { // Assume the field is a primitive and read it } } return ret; } Can't find the actual code at the moment, but that's the gist of it.
Apr 16 2014
Jeroen Bollen:Is it possible to have a structure with a dynamic size?See an usage example I have written here: http://rosettacode.org/wiki/Sokoban#Faster_Version But that code requires a very updated compiler. Otherwise you will need a little different code. Bye, bearophile
Apr 16 2014
On Wednesday, 16 April 2014 at 23:36:05 UTC, bearophile wrote:Jeroen Bollen:Just in case, the key line to pay attention to in that example is this one: CellIndex[0] c_; It is a commonly used C idiom for dynamically sized structures that D also supports.Is it possible to have a structure with a dynamic size?See an usage example I have written here: http://rosettacode.org/wiki/Sokoban#Faster_Version But that code requires a very updated compiler. Otherwise you will need a little different code. Bye, bearophile
Apr 16 2014
On Thursday, 17 April 2014 at 00:55:19 UTC, Dicebot wrote:Just in case, the key line to pay attention to in that example is this one: CellIndex[0] c_; It is a commonly used C idiom for dynamically sized structures that D also supports.Absolutely. However, from a technical point of view, it doesn't make the structure "dynamically sized". It is only a hack to access data past the end of the struct. You still have to manually and dynamically allocate the struct: auto p = cast(State*)malloc(blockSize * stateSize); And accessing data is done via .ptr, to avoid out of bounds. CellIndex get(in size_t i) inout pure nothrow { return c_.ptr[i]; }
Apr 16 2014
Dicebot:Just in case, the key line to pay attention to in that example is this one: CellIndex[0] c_;When you define dynamically sized structs it's also a good idea to wrap the items access with some kind of get/set functions, to make the code less bug-prone (and sometimes there is also a length available somewhere that those functions can use to verify the bounds in non-release builds).It is a commonly used C idiom for dynamically sized structures that D also supports.D supports zero length fixed size arrays for this usage too. And recently their .ptr was changed from null to their start addreess to improve this usage. Bye, bearophile
Apr 17 2014
Bound checked version of variable size struct: http://dpaste.dzfl.pl/fcd91d6912d3
Apr 17 2014
On Thursday, 17 April 2014 at 17:15:15 UTC, Kagamin wrote:Bound checked version of variable size struct: http://dpaste.dzfl.pl/fcd91d6912d3Well, indexes getter could take cellCount into account...
Apr 17 2014
Kagamin:Bound checked version of variable size struct: http://dpaste.dzfl.pl/fcd91d6912d3I think you are missing one of the main points of a variable sized struct, that is to reduce by 1 the number of indirection levels. Bye, bearophile
Apr 17 2014
On Thursday, 17 April 2014 at 17:35:17 UTC, bearophile wrote:Kagamin:Yeah, otherwise one could have just used dynamic array field.Bound checked version of variable size struct: http://dpaste.dzfl.pl/fcd91d6912d3I think you are missing one of the main points of a variable sized struct, that is to reduce by 1 the number of indirection levels. Bye, bearophile
Apr 17 2014
On Thursday, 17 April 2014 at 17:35:17 UTC, bearophile wrote:Kagamin:As far as I can see, my implementation has only 1 indirection level.Bound checked version of variable size struct: http://dpaste.dzfl.pl/fcd91d6912d3I think you are missing one of the main points of a variable sized struct, that is to reduce by 1 the number of indirection levels. Bye, bearophile
Apr 17 2014
On Thursday, 17 April 2014 at 17:45:22 UTC, Kagamin wrote:On Thursday, 17 April 2014 at 17:35:17 UTC, bearophile wrote:And C-like dynamic structs have 0 indirection.Kagamin:As far as I can see, my implementation has only 1 indirection level.Bound checked version of variable size struct: http://dpaste.dzfl.pl/fcd91d6912d3I think you are missing one of the main points of a variable sized struct, that is to reduce by 1 the number of indirection levels. Bye, bearophile
Apr 17 2014
State* pointer in sokoban example is a perfect 1 indirection.
Apr 17 2014
On Thursday, 17 April 2014 at 18:17:59 UTC, Kagamin wrote:State* pointer in sokoban example is a perfect 1 indirection.It is not related to actual "dynamic struct" thing, which is why I have highlighted the line to look at. Minimal example is this: struct Dynamic { size_t length; int[0] payload; } void main() { const length = 42; Dynamic* entity = alloca(Dynamic.sizeof + int.sizeof*length); entity.length = length; // pointer to same stack space so not really an indirection entity.payload[5] = 43; }
Apr 17 2014
On Thursday, 17 April 2014 at 18:29:21 UTC, Kagamin wrote:How is this different from my example?b = new byte[StateImpl.sizeof + CellIndex.sizeof*cellCount]; this line creates heap indirection
Apr 17 2014
So you assert that variable length structs can't be allocated on heap and sokoban example is a wrong example of variable length struct usage? And how heap indirection is different from stack indirection? It's still indirection.
Apr 17 2014
On Thursday, 17 April 2014 at 18:40:27 UTC, Kagamin wrote:And how heap indirection is different from stack indirection? It's still indirection.Locality. The stack is (within reason) readily available in cache.
Apr 17 2014
Well, cache locality can be optimized without reducing number of indirections, as long as the data is likely to be in cache. I agree with bearophile that variable size structs reduce number of indirections and have no direct relation to cache locality. One may have no time or no desire to initialize all the pointers or no place to put them.
Apr 17 2014
On Thu, 17 Apr 2014 14:40:25 -0400, Kagamin <spam here.lot> wrote:So you assert that variable length structs can't be allocated on heap and sokoban example is a wrong example of variable length struct usage? And how heap indirection is different from stack indirection? It's still indirection.I think the biggest issue I would have with your implementation would be if I wrapped it in another struct that I wanted to store on the heap. -Steve
Apr 17 2014
Well, it's proof of concept of bound checked variable-size struct, I wrote it in a minute. It even compiles and runs.
Apr 17 2014
On Fri, 18 Apr 2014 00:05:03 -0400, Kagamin <spam here.lot> wrote:Well, it's proof of concept of bound checked variable-size struct, I wrote it in a minute. It even compiles and runs.Please take no offense :) I just was pointing out a difference between a hand-managed and hand-written struct that I might have written and the one that you created. Depending on usage, yours might be sufficient. Note, you could probably, with mixin magic, make a version that could be emplaced inside a struct or class without an extra indirection. -Steve
Apr 18 2014
I mean, it doesn't cover all scenarios, but can be extended to support them. The indexes array does just that: it's emplaced without indirection, but still is bound checked.
Apr 18 2014
Oh, and I don't believe, that a variable-size struct can be emplaced inside fixed-size struct or class. Only as a smart pointer from the example.
Apr 18 2014
On Fri, 18 Apr 2014 12:59:35 -0400, Kagamin <spam here.lot> wrote:Oh, and I don't believe, that a variable-size struct can be emplaced inside fixed-size struct or class. Only as a smart pointer from the example.It goes at the end. Then you need to allocate the whole thing with that in mind. -Steve
Apr 18 2014
On Friday, 18 April 2014 at 13:10:28 UTC, Steven Schveighoffer wrote:Note, you could probably, with mixin magic, make a version that could be emplaced inside a struct or class without an extra indirection.Speaking about mixin magic, you probably suggest to do it overly generically, though it seems, use cases for variable size structs are specialized, specialized code and specialized data structures, so I suspect specialized approach will be more productive, intuitive, understandable, simple and straightforward for such tasks, generic approach is probably inadequate here. But if you can do it, you can try.
Apr 18 2014
On Thursday, 17 April 2014 at 17:50:30 UTC, Dicebot wrote:On Thursday, 17 April 2014 at 17:45:22 UTC, Kagamin wrote:Well, technically everything on the stack is accessed through an indirection (RBP + offset), but there are more optimisation opportunities if the base and/or offset is known statically. Performance-wise you're gaining nothing over a static array (or any alloca buffer) and potentially losing something compared to normal stack variables / struct members.On Thursday, 17 April 2014 at 17:35:17 UTC, bearophile wrote:And C-like dynamic structs have 0 indirection.Kagamin:As far as I can see, my implementation has only 1 indirection level.Bound checked version of variable size struct: http://dpaste.dzfl.pl/fcd91d6912d3I think you are missing one of the main points of a variable sized struct, that is to reduce by 1 the number of indirection levels. Bye, bearophile
Apr 17 2014
On Wednesday, 16 April 2014 at 23:36:05 UTC, bearophile wrote:Jeroen Bollen:This can illustrate 1. fairly straightforward translation of true C code to better C (bound checked D); such translation is important if one doesn't want to deeply refactor the debugged algorithm, but still reasonably gets bound checked code. 2. how easy is it to write such bound checked code. 3. developer doesn't need to design both safe and unsafe versions (as in C and C++, it can give better control of optimization, but is counterproductive, when you want to turn off safety globally), he writes safe code and gets unsafe one for free - with a compiler switch, and sees for himself, how big is performance trade-off - effortlessly, no work was spent on unsafe version, which can be another advertisement for D.Is it possible to have a structure with a dynamic size?See an usage example I have written here: http://rosettacode.org/wiki/Sokoban#Faster_Version
Apr 17 2014
On Wednesday, 16 April 2014 at 23:15:43 UTC, Jeroen Bollen wrote:Is it possible to have a structure with a dynamic size? The structure would contain an array. I know I can use templates, but the size won't be known at compile time. I also know I could just put a dynamic array into it, but that way it would just be a pointer. I know there would be major issues like how to pass the struct to a function, as it has an unknown size, but to be quite honest I just want pretty code. I'm doing network related operations. I was hoping there'd still be a way to do this using templates or so? I just don't want to go through the hassle of writing a constructor for it to fill in all the fields, and a toByteArray method to convert it back to raw data. struct MyStruct { ulong length; ubyte[length] data; // obv won't compile }Dynamic structs are impossible with D's static type system. However I suspect vibe's BSON module [1] is pretty close to what you're looking for; it has a nice API and can easily be sent in binary form. [1] http://vibed.org/api/vibe.data.bson/
Apr 16 2014