Re: sokol-d: Static Struct
On Saturday, 30 December 2023 at 19:27:08 UTC, Matheus Catarino wrote: Hi everyone. Currently I'm working on D binding for sokol project (truly a dual bindgen [sokol-tools, sokol-header]) which could be merged into the upstream project. Up to now, my "ideal" configuration has been to run all the ported examples (from other supported bindings) on Drt or betterC provided @safe has DIP1000 enabled (not obligatory). Except for the "clear" example (no have structs) works, the rest of the examples have partial execution, without 2D/3D animations, like the original ported examples. e.g.: https://github.com/kassane/sokol-d/blob/main/src/examples/sgl_context.d Finally fixed!! Works in, linux/macos/windows/wasm32(need emsdk) I was having trouble with the floating/double init (nan) and solved this issue by giving default values to structs fields. ![](https://github.com/kassane/sokol-d/assets/6756180/198f1b6b-26c0-4dfc-b372-533df1bc77d3)
Re: sokol-d: Static Struct
On Wednesday, 3 January 2024 at 18:57:44 UTC, ryuukk_ wrote: I managed to compile your project, ``sgl_context`` is working for me, it renders and roate [...] Wow! Cube and blend work, too? And on my machine it doesn't rotate, just like I initially posted. I had to remove this from your build script tho: ``try cmds.append(b.fmt("--mcpu={s}", .{lib.target.getCpuModel().name}));`` [...] Please! This deserves opening an issue about it. Because Zig is normally set native build by default. What version of LDC is used? 1.35?
Re: sokol-d: Static Struct
On Wednesday, 3 January 2024 at 17:50:19 UTC, Matheus Catarino wrote: On Saturday, 30 December 2023 at 20:20:50 UTC, ryuukk_ wrote: I suspect you have a typo in one of your definition I debugged some existing bindings, and despite any user-level errors (via code) there's some conflict between ABIs. In fact, it's mentioned by sokol's author below: I've been seeing weird platform-specific ABI related issues in language bindings where the struct params were corrupted on their way to the other language (for instance in Zig on Intel Macs). https://github.com/kassane/sokol-d/issues/5#issuecomment-1875665075 I managed to compile your project, ``sgl_context`` is working for me, it renders and roate I had to remove this from your build script tho: ``try cmds.append(b.fmt("--mcpu={s}", .{lib.target.getCpuModel().name}));`` Otherwise it crashes ``` ryuukk@ark:~/dev/tmp/sokol-d (main) $ zig build sgl_context && ./zig-out/bin/sgl_context 'x86_64' is not a recognized processor for this target (ignoring processor) 'x86_64' is not a recognized processor for this target (ignoring processor) /home/ryuukk/dev/tmp/sokol-d/src/examples/sgl_context.d(36,20): `display` is thread local /home/ryuukk/dev/tmp/sokol-d/src/examples/sgl_context.d(37,22): `offscreen` is thread local 'x86_64' is not a recognized processor for this target (ignoring processor) 'x86_64' is not a recognized processor for this target (ignoring processor) 'x86_64' is not a recognized processor for this target (ignoring processor) 'x86_64' is not a recognized processor for this target (ignoring processor) LLVM ERROR: 64-bit code requested on a subtarget that doesn't support it! #0 0x7f8df5c1f503 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/usr/lib/libLLVM-16.so+0xe1f503) #1 0x7f8df5c1c7bf llvm::sys::RunSignalHandlers() (/usr/lib/libLLVM-16.so+0xe1c7bf) #2 0x7f8df5c1c90d (/usr/lib/libLLVM-16.so+0xe1c90d) #3 0x7f8df485c710 (/usr/lib/libc.so.6+0x3e710) #4 0x7f8df48ac83c (/usr/lib/libc.so.6+0x8e83c) #5 0x7f8df485c668 gsignal (/usr/lib/libc.so.6+0x3e668) #6 0x7f8df48444b8 abort (/usr/lib/libc.so.6+0x264b8) #7 0x7f8df594d25f (/usr/lib/libLLVM-16.so+0xb4d25f) #8 0x7f8df5b1f19e (/usr/lib/libLLVM-16.so+0xd1f19e) #9 0x7f8df999688c (/usr/lib/libLLVM-16.so+0x4b9688c) #10 0x7f8df99970b9 (/usr/lib/libLLVM-16.so+0x4b970b9) #11 0x7f8df999eb48 (/usr/lib/libLLVM-16.so+0x4b9eb48) #12 0x7f8df999ee95 (/usr/lib/libLLVM-16.so+0x4b9ee95) #13 0x7f8df822d39a (/usr/lib/libLLVM-16.so+0x342d39a) #14 0x7f8df78e9556 llvm::TargetIRAnalysis::run(llvm::Function const&, llvm::AnalysisManager&) (/usr/lib/libLLVM-16.so+0x2ae9556) #15 0x7f8df6a42b48 (/usr/lib/libLLVM-16.so+0x1c42b48) #16 0x7f8df5dfbe7e llvm::AnalysisManager::getResultImpl(llvm::AnalysisKey*, llvm::Function&) (/usr/lib/libLLVM-16.so+0xffbe7e) #17 0x7f8df75c9af0 llvm::AssumptionAnalysis::run(llvm::Function&, llvm::AnalysisManager&) (/usr/lib/libLLVM-16.so+0x27c9af0) #18 0x7f8df6a839d2 (/usr/lib/libLLVM-16.so+0x1c839d2) #19 0x7f8df5dfbe7e llvm::AnalysisManager::getResultImpl(llvm::AnalysisKey*, llvm::Function&) (/usr/lib/libLLVM-16.so+0xffbe7e) #20 0x7f8df75daecb llvm::BasicAA::run(llvm::Function&, llvm::AnalysisManager&) (/usr/lib/libLLVM-16.so+0x27daecb) #21 0x7f8df9b7086f (/usr/lib/libLLVM-16.so+0x4d7086f) #22 0x7f8df5dfbe7e llvm::AnalysisManager::getResultImpl(llvm::AnalysisKey*, llvm::Function&) (/usr/lib/libLLVM-16.so+0xffbe7e) #23 0x7f8df9bd352c (/usr/lib/libLLVM-16.so+0x4dd352c) #24 0x7f8df75b760b llvm::AAManager::run(llvm::Function&, llvm::AnalysisManager&) (/usr/lib/libLLVM-16.so+0x27b760b) #25 0x7f8df7957b39 (/usr/lib/libLLVM-16.so+0x2b57b39) #26 0x7f8df5dfbe7e llvm::AnalysisManager::getResultImpl(llvm::AnalysisKey*, llvm::Function&) (/usr/lib/libLLVM-16.so+0xffbe7e) #27 0x7f8df71fc56b llvm::AlwaysInlinerPass::run(llvm::Module&, llvm::AnalysisManager&) (/usr/lib/libLLVM-16.so+0x23fc56b) #28 0x7f8df9b727f6 (/usr/lib/libLLVM-16.so+0x4d727f6) #29 0x7f8df5df8466 llvm::PassManagerllvm::AnalysisManager>::run(llvm::Module&, llvm::AnalysisManager&) (/usr/lib/libLLVM-16.so+0xff8466) #30 0x558a65baa7a2 runOptimizationPasses(llvm::Module*) (/usr/bin/ldc2+0x9c37a2) #31 0x558a65bac10f ldc_optimize_module(llvm::Module*) (/usr/bin/ldc2+0x9c510f) #32 0x558a65c92c2d writeModule(llvm::Module*, char const*) (/usr/bin/ldc2+0xaabc2d) #33 0x558a65c8d1f8 ldc::CodeGenerator::writeAndFreeLLModule(char const*) (/usr/bin/ldc2+0xaa61f8) #34 0x558a65c56512 codegenModules(Array&) (/usr/bin/ldc2+0xa6f512) #35 0x558a658a6728 mars_mainBody(Param&, Array&, Array&) (/usr/bin/ldc2+0x6bf728) #36 0x558a65c547c7 cppmain() (/usr/bin/ldc2+0xa6d7c7) #37 0x558a65dffa9d _D2rt6dmain212_d_run_main2UAAamPUQgZiZ6runAllMFZv (/usr/bin/ldc2+0xc18a9d) #38 0x558a65dff8b7 _d_run_main2 (/usr/bin/ldc2+0xc188b7) #39
Re: sokol-d: Static Struct
On Saturday, 30 December 2023 at 20:20:50 UTC, ryuukk_ wrote: I suspect you have a typo in one of your definition I debugged some existing bindings, and despite any user-level errors (via code) there's some conflict between ABIs. In fact, it's mentioned by sokol's author below: I've been seeing weird platform-specific ABI related issues in language bindings where the struct params were corrupted on their way to the other language (for instance in Zig on Intel Macs). https://github.com/kassane/sokol-d/issues/5#issuecomment-1875665075
Re: sokol-d: Static Struct
Use https://renderdoc.org/ and check and compare frames for both your working and non-working example Nice!! I'll try. That'll give you an idea at what could be wrong I suspect you have a typo in one of your definition I don't doubt it. I'm experiencing D in just a week. (Newbie) On Saturday, 30 December 2023 at 20:56:39 UTC, Renato wrote: Sorry if I sidetrack the discussion, but I was amazed by the Zig build file in that project: https://github.com/kassane/sokol-d/blob/main/build.zig Do you have more information about how to integrate C and D using Zig as the build tool?? That sounds very interesting. Hi Renato, I'm glad you liked it. This is an experiment, as I haven't adapted to the dub yet. Zig's goal at this point is to share `libsokol` configurations and replicate in the D compiler (currently, ldc2 only). If you want to see the result, just run `zig build clear --verbose`. ``` -> build(exe) -> build libsokol -> (optional) zigcc-wrapper -> build D example (using libsokol config) -> switch (cc/linker system or zigcc) -> binary (exe/lib) ``` I added some comments to `build.zig` explaining each point. If you have any questions, you can ask in the repo. I saw that you are a MacOS user, I suggest you see issue/1 [closed] focused on zigcc wrapper. **TODO:** It is intended to add dub support and will continue with Zig build-system support, including zig-pkg(v0.12.0/master - git url) for downloading and integrating C and D packages.
Re: sokol-d: Static Struct
On Saturday, 30 December 2023 at 19:27:08 UTC, Matheus Catarino wrote: Hi everyone. Currently I'm working on D binding for sokol project (truly a dual bindgen [sokol-tools, sokol-header]) which could be merged into the upstream project. Sorry if I sidetrack the discussion, but I was amazed by the Zig build file in that project: https://github.com/kassane/sokol-d/blob/main/build.zig Do you have more information about how to integrate C and D using Zig as the build tool?? That sounds very interesting.
Re: sokol-d: Static Struct
Use https://renderdoc.org/ and check and compare frames for both your working and non-working example That'll give you an idea at what could be wrong I suspect you have a typo in one of your definition I'll try to take a look later
sokol-d: Static Struct
Hi everyone. Currently I'm working on D binding for sokol project (truly a dual bindgen [sokol-tools, sokol-header]) which could be merged into the upstream project. Up to now, my "ideal" configuration has been to run all the ported examples (from other supported bindings) on Drt or betterC provided @safe has DIP1000 enabled (not obligatory). Except for the "clear" example (no have structs) works, the rest of the examples have partial execution, without 2D/3D animations, like the original ported examples. e.g.: https://github.com/kassane/sokol-d/blob/main/src/examples/sgl_context.d Based on the articles in the official documentation, I tried to use `__gshared` (no `@safe`) to attribute both the display and offscreen structures inside state, but it didn't work. ```d @disable struct State { @disable this(); @disable this(this); __gshared Display display; __gshared Offscreen offscreen; } static assert(!__traits(isDisabled, State)); static assert(!__traits(isCopyable, State)); ``` ## Reproduce ![sokol_d_sglcontext](https://github.com/kassane/sokol-d/assets/6756180/0e8391f6-056e-46db-b8e8-021309954ffe) ## Expected ![sokol_zig_sglcontext](https://github.com/kassane/sokol-d/assets/6756180/576176f8-005a-408d-9ae7-00948161b19f)
Re: Static struct initialization syntax behavior & it being disabled upon adding a constructor
On 4/18/22 09:17, Ali Çehreli wrote: > shared static ~this(): 0 > static ~this(): 0 >~this(): 8 Apologies for omitting 'scope' statements: scope(exit): 34 scope(success): 6 scope(failure): 8 Ali
Re: Static struct initialization syntax behavior & it being disabled upon adding a constructor
On 4/17/22 17:35, Ali Çehreli wrote: > compared to C++, the amount of constructor, destructor, copy > constructor, etc. that I do *not* write in D is very liberating to me. > It feels like I just write what is needed and it mostly just works. The following is a quick and dirty grep-based stats from a largish successful project that implements multiple libraries and binaries. The figures are numbers of times each construct appears in source code: struct: 231 interface: 3 class: 12 union: 0 this(/* ... */): 72 [1] shared static this(): 8 static this(): 1 [2] shared static ~this(): 0 static ~this(): 0 ~this(): 8 this(this): 0 [3] [1] Most operations in most constructors are trivial assignments to members. [2] It contains just an enforce expression to ensure the environment is as expected. (It is an oversight that this is not a 'shared static this' as well.) [3] There are no copy constructors either because the project started with an older compiler. It is remarkable that I did not implement a single copy or move behavior ever. Compare that to countless C++ articles on attempting to teach how to deal with fundamental operations of object. Forgotten to be called or not, there are no 'move' (which does not move in C++) or 'forward' (which does not forward in C++) expressions at all. What a price the programming community keeps on paying just because their powerful programming language was there first... Ali
Re: Static struct initialization syntax behavior & it being disabled upon adding a constructor
On Mon, Apr 18, 2022 at 08:22:26AM +, cc via Digitalmars-d-learn wrote: > On Monday, 18 April 2022 at 03:21:30 UTC, H. S. Teoh wrote: > > Structs in D ought to be treated like "glorified ints", as Andrei > > puts it. If you need complex ctors and complex methods, that's a > > sign you should be using a class instead. > > Unless you're having a nice quiet get-together with friends, and you > don't want to invite the GC, the biggest loudest party animal on the > block. Phobos's RefCounted seems to stretch the definition of > "glorified ints".. "Glorified int" includes pass-by-value types like pointers. Pointers / references wrapped in a struct is one of the more powerful D constructs that lets you do some pretty neat things. (Just don't expect it to behave like C++, lol. :-P) T -- Debian GNU/Linux: Cray on your desktop.
Re: Static struct initialization syntax behavior & it being disabled upon adding a constructor
On Monday, 18 April 2022 at 13:21:44 UTC, zjh wrote: I hope that d can support it like `C++`. `Struct` and `class` behavior is inconsistent. `Constructors` sometimes have initialize behavior. If D doesn't think about `C++` users, `C++` users feel too troublesome, can't understand, and the cognitive burden is too heavy.
Re: Static struct initialization syntax behavior & it being disabled upon adding a constructor
On Sunday, 17 April 2022 at 15:13:29 UTC, HuskyNator wrote: This is a twofold question, along the example code below: The `default constructor` of `struct` is very convenient to use. I hope that d can support it like `C++`.
Re: Static struct initialization syntax behavior & it being disabled upon adding a constructor
On Monday, 18 April 2022 at 10:26:16 UTC, HuskyNator wrote: On a sidenote, I'm surprised D did not choose 0 as the default floating value. Doesn't almost every language do this? I understand the thinking behind it, but when the type one uses in a template influences the behavior of the code, that seems like a pretty big red flag to me. (Any non-floating type defaults to 0, but using floats/doubles suddenly introduces NaN, surely I'm not the only one that sees a problem with this ) Especially when it's basically a standard 0 is used for this. Sorry for the rant. Let me explain the why: D default initialization is not designed to replace user-defined initialization, it's rather made to make bugs related to non-initialized variables stable, e.g not UB. The easiest way to get that is to think to references and pointers. A random garbage value pointed by an alloca may work to some point (e.g access to member), if it's set to `null` right after the alloca then you have a stable segfault that always happens at the same time and is easy to debug. Similarly, for floating point numbers the D designers considered that `NaN` was the best choice because FP operations will not wrongly appear valid when starting operations with NaN. With integral types, this system does not work as well, as `0` doesn't create bugs as easily as `null` and `NaN`. The confusion about the real role of default initialization comes from integral types I believe.
Re: Static struct initialization syntax behavior & it being disabled upon adding a constructor
On Monday, 18 April 2022 at 10:26:16 UTC, HuskyNator wrote: On a sidenote, I'm surprised D did not choose 0 as the default floating value. Doesn't almost every language do this? I understand the thinking behind it, but when the type one uses in a template influences the behavior of the code, that seems like a pretty big red flag to me. (Any non-floating type defaults to 0, but using floats/doubles suddenly introduces NaN, surely I'm not the only one that sees a problem with this ) Especially when it's basically a standard 0 is used for this. Sorry for the rant. I agree, it's a hiccup. I have at times intentionally initialized a float as NaN so that I can identify later whether an appropriate value has been assigned, but I've never seen the need to have this be the default behavior when integer types always init to 0 (more specifically, init to a MODIFYABLE value). In game design I have tons upon tons of floats that all [should] start initialized to zero. I can add 4 to a declared but not-assigned-to int and it'll be 4, a float remains NaN. Having to manually declare appropriate init values to each one doesn't aid me in detecting "bugs". If I had an int that was supposed to default to 10 instead of 0 it would still be a bug if I forgot to specify that, tripping me up for falsely assuming floats would start at 0 doesn't aid my workflow in any way. The whole "you should pay more attention to what you're initializing, o buggy programmer you" philosophy seems like something that should be reserved for pointers and reference types, not basic numeric data. It's probably set in stone by this point though and too late to change. Ten years ago, almost to the day: https://forum.dlang.org/thread/thsjtreegdwcgbazh...@forum.dlang.org The reasoning still feels flimsy and stubborn.
Re: Static struct initialization syntax behavior & it being disabled upon adding a constructor
On Monday, 18 April 2022 at 03:21:30 UTC, H. S. Teoh wrote: Structs in D ought to be treated like "glorified ints", as Andrei puts it. If you need complex ctors and complex methods, that's a sign you should be using a class instead. I prefer not to use classes, as the code would now move towards using references, which is the exact reason I'm using structs. I ended up creating a constructor for my needs and disabling the default constructor. I'm mostly just surprised the static syntax is turned off by adding one. I still don't see the reason behind it. Why have it but disable it? I ironically almost always need the exact same constructor with the identical arguments though: Initialize the matrix to the identity matrix. Why not introduce the empty self-defined constructor as a separate thing from the .init value? On a sidenote, I'm surprised D did not choose 0 as the default floating value. Doesn't almost every language do this? I understand the thinking behind it, but when the type one uses in a template influences the behavior of the code, that seems like a pretty big red flag to me. (Any non-floating type defaults to 0, but using floats/doubles suddenly introduces NaN, surely I'm not the only one that sees a problem with this ) Especially when it's basically a standard 0 is used for this. Sorry for the rant.
Re: Static struct initialization syntax behavior & it being disabled upon adding a constructor
On Monday, 18 April 2022 at 03:21:30 UTC, H. S. Teoh wrote: Structs in D ought to be treated like "glorified ints", as Andrei puts it. If you need complex ctors and complex methods, that's a sign you should be using a class instead. Unless you're having a nice quiet get-together with friends, and you don't want to invite the GC, the biggest loudest party animal on the block. Phobos's RefCounted seems to stretch the definition of "glorified ints"..
Re: Static struct initialization syntax behavior & it being disabled upon adding a constructor
On Sun, Apr 17, 2022 at 05:35:13PM -0700, Ali Çehreli via Digitalmars-d-learn wrote: > On 4/17/22 08:13, HuskyNator wrote: [...] > > - 2: Why does adding a constructor to a struct disable the use of > > the static initialization syntax? > > I am not sure how to answer this question because I am about to say > don't use the static initialization syntax. :/ To me, idiomatic way of > constructing D objects is > > auto m = Mat!2([1,2]); > > The reason why one cannot define a default constructor for a D struct > is because every type in D must have a statically known .init value. A > user-defined default constructor could not be known at compile time. IME, when the lack of default ctors in D starts bothering me, that's usually around the time the struct really ought to be rewritten as a class (which *does* support default ctors). Structs in D ought to be treated like "glorified ints", as Andrei puts it. If you need complex ctors and complex methods, that's a sign you should be using a class instead. [...] > Really, compared to C++, the amount of constructor, destructor, copy > constructor, etc. that I do *not* write in D is very liberating to me. > It feels like I just write what is needed and it mostly just works. [...] One thing about idiomatic D code is that it embraces the "create the object first, then kick it into shape" philosophy, vs. the "meticulously manage the initialization of every last bit in the ctor so that the object comes out of the ctor call a perfect product ready to ship" philosophy. The latter requires a lot of boilerplate and micromanagement of object state; the former, when done well, leads to streamlined code that gets its job done with a minimum of fuss. T -- Never criticize a man until you've walked a mile in his shoes. Then when you do criticize him, you'll be a mile away and he won't have his shoes.
Re: Static struct initialization syntax behavior & it being disabled upon adding a constructor
On 4/17/22 08:13, HuskyNator wrote: > - 1: Why does `m` initialization behave as if `m[0][]=1` and `m[1][]=2` > were used? (Shouldn't this code result in an error instead?) That's pretty weird. I think it boils down to scalar assignment to an array being valid: void main() { int[3] arr; arr = 42;// Feature? (Yes.) import std.algorithm : all; assert(arr[].all!(e => e == 42)); } So, in the end, each element of your argument array gets assigned to each element of member array. Makes sense (to me :) )... I think the initialization of 'n' is more straightforward. > - 2: Why does adding a constructor to a struct disable the use of the > static initialization syntax? I am not sure how to answer this question because I am about to say don't use the static initialization syntax. :/ To me, idiomatic way of constructing D objects is auto m = Mat!2([1,2]); The reason why one cannot define a default constructor for a D struct is because every type in D must have a statically known .init value. A user-defined default constructor could not be known at compile time. > it now requires me to > write additional constructors, as soon as I want to add 1. I don't see it as a big problem in practice. As soon as I need to add a constructor, the default behavior of setting members to arguments seems out of place. Either the one constructor is sufficient or write at most another one at most. > the commonly suggested workarounds (using `opCall`) seems > rather inelegant to me. Agreed. And static opCall() is not usable in all cases as it somehow conflicts in some cases. (Don't remember now.) > Why is this possible in C++ in contrast? C++ does not insist that all types have a statically known .init value. If I'm not mistaken, the part about disabling certain constructors, move or otherwise, is commonly accepted in C++ as well. Really, compared to C++, the amount of constructor, destructor, copy constructor, etc. that I do *not* write in D is very liberating to me. It feels like I just write what is needed and it mostly just works. Ali
Static struct initialization syntax behavior & it being disabled upon adding a constructor
This is a twofold question, along the example code below: - 1: Why does `m` initialization behave as if `m[0][]=1` and `m[1][]=2` were used? (Shouldn't this code result in an error instead?) - 2: Why does adding a constructor to a struct disable the use of the static initialization syntax? I only see it mentioned in the documentation indirectly (there are notes in the example code specifying as such, but the text itself does not seem to define their removal). I also don't see how this behavior is beneficial, as it now requires me to write additional constructors, as soon as I want to add 1. ```d struct Mat(int n){ int[n][n] mat; void write(){ writeln(mat); } // Will cause the m & n initialisations to yield errors. // this(int i){ // mat[0][0] = i; // } } void main() { Mat!2 m = {[1,2]}; // Prints [[1, 1], [2, 2]] Mat!2 n = {[[1,2],[3,4]]}; // Prints [[1, 2], [3, 4]] m.write(); n.write(); } ``` PS: Are there any plans to change the behaviour of empty struct constructors? (eg: `this(){}`) It surprised me greatly coming into D, and one of the commonly suggested workarounds (using `opCall`) seems rather inelegant to me. Why is this possible in C++ in contrast?
Re: Nasty supprise when using c 'anonymous struct and union' in D with 'static struct'
On Tue, Dec 29, 2020 at 12:50:06PM -0500, Steven Schveighoffer via Digitalmars-d-learn wrote: > On 12/29/20 12:45 PM, H. S. Teoh wrote: [...] > > You need to add 'static' to the (outer) struct declarations in your > > unittest block, because otherwise they *will* have a context > > pointer. > > Not if the struct is POD. And in this case, they are all POD (no > methods). [...] Hmm, I didn't know that! I thought they always get a context pointer. Maybe I got confused with nested functions. I stand corrected. --T
Re: Nasty supprise when using c 'anonymous struct and union' in D with 'static struct'
On Tuesday, 29 December 2020 at 17:49:20 UTC, Steven Schveighoffer wrote: On 12/29/20 12:13 PM, Arjan wrote: On Tuesday, 29 December 2020 at 14:42:07 UTC, Steven Schveighoffer wrote: On 12/29/20 7:38 AM, Arjan wrote: see https://en.cppreference.com/w/c/language/struct structs only add context pointers if nested in functions (and even then, only if it's not POD). If nested in structs, classes, or unions (or anything else), then no context pointer is added. So the answer is, don't use static. That is what I discovered indeed. Thanks both for answering and the additional information. This could however be made more explicit and clear in the documentation.
Re: Nasty supprise when using c 'anonymous struct and union' in D with 'static struct'
On 12/29/20 12:45 PM, H. S. Teoh wrote: On Tue, Dec 29, 2020 at 05:13:19PM +, Arjan via Digitalmars-d-learn wrote: [...] On the C/C++ side there is no static. I added those on the D side to to make sure there is no context pointer being added, since that will change the layout and size of struct. (in the c/c++ code those unions and structs are nested several levels deep) You need to add 'static' to the (outer) struct declarations in your unittest block, because otherwise they *will* have a context pointer. Not if the struct is POD. And in this case, they are all POD (no methods). -Steve
Re: Nasty supprise when using c 'anonymous struct and union' in D with 'static struct'
On 12/29/20 12:13 PM, Arjan wrote: On Tuesday, 29 December 2020 at 14:42:07 UTC, Steven Schveighoffer wrote: On 12/29/20 7:38 AM, Arjan wrote: see https://en.cppreference.com/w/c/language/struct I added in some printouts of the addresses of the variables. It appears that if you add static to the struct, it now becomes a static member of the union, which means it's not an instance variable, and is now a thread-local variable. Its address doesn't even coincide remotely with the address of v1. What is the equivalent behavior for C that you are expecting? The usage of "static struct" doesn't appear in that page you linked to. On the C/C++ side there is no static. I added those on the D side to to make sure there is no context pointer being added, since that will change the layout and size of struct. (in the c/c++ code those unions and structs are nested several levels deep) Based on this: https://dlang.org/spec/struct.html#nested I expected to have the equivalent of C behavior in D by using the static keyword, which in this case just caused havoc. So the other way around. structs only add context pointers if nested in functions (and even then, only if it's not POD). If nested in structs, classes, or unions (or anything else), then no context pointer is added. So the answer is, don't use static. -Steve
Re: Nasty supprise when using c 'anonymous struct and union' in D with 'static struct'
On Tue, Dec 29, 2020 at 05:13:19PM +, Arjan via Digitalmars-d-learn wrote: [...] > On the C/C++ side there is no static. I added those on the D side to > to make sure there is no context pointer being added, since that will > change the layout and size of struct. (in the c/c++ code those unions > and structs are nested several levels deep) You need to add 'static' to the (outer) struct declarations in your unittest block, because otherwise they *will* have a context pointer. This is because unittest blocks are compiled as if they were functions, and struct declarations in a function do acquire context pointers. --T
Re: Nasty supprise when using c 'anonymous struct and union' in D with 'static struct'
On Tuesday, 29 December 2020 at 14:42:07 UTC, Steven Schveighoffer wrote: On 12/29/20 7:38 AM, Arjan wrote: see https://en.cppreference.com/w/c/language/struct I added in some printouts of the addresses of the variables. It appears that if you add static to the struct, it now becomes a static member of the union, which means it's not an instance variable, and is now a thread-local variable. Its address doesn't even coincide remotely with the address of v1. What is the equivalent behavior for C that you are expecting? The usage of "static struct" doesn't appear in that page you linked to. On the C/C++ side there is no static. I added those on the D side to to make sure there is no context pointer being added, since that will change the layout and size of struct. (in the c/c++ code those unions and structs are nested several levels deep) Based on this: https://dlang.org/spec/struct.html#nested I expected to have the equivalent of C behavior in D by using the static keyword, which in this case just caused havoc. So the other way around.
Re: Nasty supprise when using c 'anonymous struct and union' in D with 'static struct'
On 12/29/20 7:38 AM, Arjan wrote: see https://en.cppreference.com/w/c/language/struct It seems the 'static' must NOT be used here to get the equivalent behavior of c, when left in the assertions will fail. Is this expected? ``` unittest { struct W { align(1): long k; long l; } struct V { align(1): union // anonymous union { /*static*/ struct // anonymous structure { long i; long j; } W w; } int m; } V v1; v1.i = 2; assert( 2 == v1.w.k ); v1.w.l = 5; assert( 5 == v1.j ); } ``` I added in some printouts of the addresses of the variables. It appears that if you add static to the struct, it now becomes a static member of the union, which means it's not an instance variable, and is now a thread-local variable. Its address doesn't even coincide remotely with the address of v1. What is the equivalent behavior for C that you are expecting? The usage of "static struct" doesn't appear in that page you linked to. -Steve
Nasty supprise when using c 'anonymous struct and union' in D with 'static struct'
see https://en.cppreference.com/w/c/language/struct It seems the 'static' must NOT be used here to get the equivalent behavior of c, when left in the assertions will fail. Is this expected? ``` unittest { struct W { align(1): long k; long l; } struct V { align(1): union // anonymous union { /*static*/ struct // anonymous structure { long i; long j; } W w; } int m; } V v1; v1.i = 2; assert( 2 == v1.w.k ); v1.w.l = 5; assert( 5 == v1.j ); } ```
Re: Static struct?
On Wed, Apr 24, 2019 at 09:12:10PM +, JN via Digitalmars-d-learn wrote: > I noticed a construct I haven't seen before in D when reading the > description for automem - https://github.com/atilaneves/automem > > static struct Point { > int x; > int y; > } > > > What does "static" do in this case? How does it different to a normal > struct? In module-global scope, nothing. In function/aggregate scope, means the struct won't have the hidden context pointer to its lexical container, so you won't be able to access variables from the containing scope. OTOH, it also makes it possible to instantiate the struct outside that scope (since otherwise it's not possible to construct it with the proper context pointer). So ironically, 'static' in this case actually means "normal", as opposed to a struct that carries a hidden context pointer and has restrictions as to where/how it can be used. T -- Frank disagreement binds closer than feigned agreement.
Re: Static struct?
On Wednesday, 24 April 2019 at 21:12:10 UTC, JN wrote: I noticed a construct I haven't seen before in D when reading the description for automem - https://github.com/atilaneves/automem static struct Point { int x; int y; } What does "static" do in this case? How does it different to a normal struct? It's like if it's declared at the global scope, meaning that it doesn't know the context and cant access, if declared in a function, the stack frame. Now dependeding on the location, static can be a noop. module foo; static struct One {} // noop void bar() { int i; static struct Two { void stuff(){ i = 42:} } // error } void baz() { int i; struct Three { void stuff(){ i = 42:} } // ok }
Re: Static struct?
On Wednesday, 24 April 2019 at 21:12:10 UTC, JN wrote: I noticed a construct I haven't seen before in D when reading the description for automem - https://github.com/atilaneves/automem static struct Point { int x; int y; } What does "static" do in this case? How does it different to a normal struct? You can access variables in the current scope when in a nested scope, static prevents this so that you don't accidentally access any of those values as it adds overhead to the struct. https://run.dlang.io/is/QNumbz void main() { import std.stdio; int x; struct A { void test() { x = 10; } } static struct B { // void test() { x = 20; } // Error } A a; B b; a.test(); // b.test(); writeln( x ); }
Static struct?
I noticed a construct I haven't seen before in D when reading the description for automem - https://github.com/atilaneves/automem static struct Point { int x; int y; } What does "static" do in this case? How does it different to a normal struct?
Re: UDA and static struct fields
On Thursday, 24 May 2018 at 10:42:26 UTC, Andrea Fontana wrote: On Thursday, 24 May 2018 at 10:23:41 UTC, Andrea Fontana wrote: On Thursday, 24 May 2018 at 09:17:10 UTC, Alex wrote: On Thursday, 24 May 2018 at 08:48:30 UTC, Andrea Fontana wrote: This line: mixin("alias tmp = " ~ s ~ ";"); There's no mention of Symbol in there. If you change it to this: mixin("alias tmp = Symbol" ~ s ~ ";"); then suddenly things work. -- Simen What? a dot is missing, but essentially, Simen found it :) Line 20 in https://run.dlang.io/is/OGHJYX should be: mixin("alias tmp = Symbol." ~ s ~ ";"); Whoops I didn't get it. Thank you both. Andrea Why didn't that return any error, anyway? Because: mixin("alias tmp = " ~ s ~ ";"); Translates to: alias tmp = i; And i will be the global i.
Re: UDA and static struct fields
On Thursday, 24 May 2018 at 10:23:41 UTC, Andrea Fontana wrote: On Thursday, 24 May 2018 at 09:17:10 UTC, Alex wrote: On Thursday, 24 May 2018 at 08:48:30 UTC, Andrea Fontana wrote: This line: mixin("alias tmp = " ~ s ~ ";"); There's no mention of Symbol in there. If you change it to this: mixin("alias tmp = Symbol" ~ s ~ ";"); then suddenly things work. -- Simen What? a dot is missing, but essentially, Simen found it :) Line 20 in https://run.dlang.io/is/OGHJYX should be: mixin("alias tmp = Symbol." ~ s ~ ";"); Whoops I didn't get it. Thank you both. Andrea Why didn't that return any error, anyway?
Re: UDA and static struct fields
On Thursday, 24 May 2018 at 09:17:10 UTC, Alex wrote: On Thursday, 24 May 2018 at 08:48:30 UTC, Andrea Fontana wrote: This line: mixin("alias tmp = " ~ s ~ ";"); There's no mention of Symbol in there. If you change it to this: mixin("alias tmp = Symbol" ~ s ~ ";"); then suddenly things work. -- Simen What? a dot is missing, but essentially, Simen found it :) Line 20 in https://run.dlang.io/is/OGHJYX should be: mixin("alias tmp = Symbol." ~ s ~ ";"); Whoops I didn't get it. Thank you both. Andrea
Re: UDA and static struct fields
On Thursday, 24 May 2018 at 08:48:30 UTC, Andrea Fontana wrote: This line: mixin("alias tmp = " ~ s ~ ";"); There's no mention of Symbol in there. If you change it to this: mixin("alias tmp = Symbol" ~ s ~ ";"); then suddenly things work. -- Simen What? a dot is missing, but essentially, Simen found it :) Line 20 in https://run.dlang.io/is/OGHJYX should be: mixin("alias tmp = Symbol." ~ s ~ ";");
Re: UDA and static struct fields
On Thursday, 24 May 2018 at 07:59:08 UTC, Simen Kjærås wrote: On Thursday, 24 May 2018 at 07:47:54 UTC, Andrea Fontana wrote: Is this a bug or am I missing something? https://run.dlang.io/is/OGHJYX Andrea This line: mixin("alias tmp = " ~ s ~ ";"); There's no mention of Symbol in there. If you change it to this: mixin("alias tmp = Symbol" ~ s ~ ";"); then suddenly things work. -- Simen What?
Re: UDA and static struct fields
On Thursday, 24 May 2018 at 07:47:54 UTC, Andrea Fontana wrote: Is this a bug or am I missing something? https://run.dlang.io/is/OGHJYX Andrea This line: mixin("alias tmp = " ~ s ~ ";"); There's no mention of Symbol in there. If you change it to this: mixin("alias tmp = Symbol" ~ s ~ ";"); then suddenly things work. -- Simen
UDA and static struct fields
Is this a bug or am I missing something? https://run.dlang.io/is/OGHJYX Andrea
Re: Can I use memoize with a non-static struct method?
On Tuesday, 26 December 2017 at 00:47:14 UTC, Marc wrote: something like this: struct S { // variables... string doGen(int n) { return ""; } alias gen = memoize!doGen; } The error I got is: Error: need 'this' for 'doGen' of type 'string(int n)' I can't make doGen static because it access non-static struct members... can I workaround this? i don't want to mislead you and i don't know if this is somehow possible but what about some ufcs magic? string doGen(S s, int n) { return "hello ".repeat().take(n).join(); } struct S { int x; auto gen() @property { return memoize!doGen(this, x); } } void main() { S s = S(5); s.gen.writeln; s.x = 10; s.gen.writeln; s.x = 15; s.gen.writeln; s.x = 20; s.gen.writeln; }
Can I use memoize with a non-static struct method?
something like this: struct S { // variables... string doGen(int n) { return ""; } alias gen = memoize!doGen; } The error I got is: Error: need 'this' for 'doGen' of type 'string(int n)' I can't make doGen static because it access non-static struct members... can I workaround this?
Re: Why no offsetof for static struct?
On 07/10/2017 11:14 PM, FoxyBrown wrote: auto GetStaticAddress(T)() { mixin("auto p = cast(T*)"~__traits(allMembers, T)[0]~";"); return p; } Returns the address of a struct's static members. No, it returns the address of T's first member. It's pretty obvious, the compiler seems to instantiate the static members simply as a sort of "singleton". They are laid out with the same relative offsets as the struct(which is obvious, as that is the most natural way). That is all that is needed to treat the memory the static variables use as the struct in which they are part of. No need to make it any more complex than that. There may be cases where that happens, but it's not guaranteed. Here's an example where static members don't get stored together: struct SA { static int x; static immutable int y; } struct SB { static int x; static immutable int y; } struct D { int x; immutable int y; } const(void)*[] addressesOfMembers(alias thing)() { import std.meta: AliasSeq; static if (is(thing)) alias T = thing; else alias T = typeof(thing); const(void)*[] addresses; foreach (m; AliasSeq!(__traits(allMembers, T))) { addresses ~= &__traits(getMember, thing, m); } return addresses; } void main() { import std.stdio; writeln("members of SA: ", addressesOfMembers!SA); writeln("members of SB: ", addressesOfMembers!SB); D d; writeln("members of d: ", addressesOfMembers!d); } Prints something like this (Ubuntu, x86-64): members of SA: [7F7B2A294E90, 55EB7957FE94] members of SB: [7F7B2A294E94, 55EB7957FE9C] members of d: [7FFDD1F2E4B8, 7FFDD1F2E4BC] Note that SA's second member is stored far away from its first member. Same for SB. Also, SB's second member is stored between SA's members. In contrast, d's members are packed together, because they're not static.
Re: Why no offsetof for static struct?
On 7/11/2017 6:14 AM, FoxyBrown wrote: On Monday, 10 July 2017 at 20:13:46 UTC, Adam D. Ruppe wrote: No, it isn't. Static members are stored in an entirely different place than non-static members. They are really just global variables in memory with their in-source name being nested somewhere else. This is not true, just because there isn't any official statement, or even if denied, does not make it true. I have proof: auto GetStaticAddress(T)() { mixin("auto p = cast(T*)"~__traits(allMembers, T)[0]~";"); return p; } Returns the address of a struct's static members. It's pretty obvious, the compiler seems to instantiate the static members simply as a sort of "singleton". They are laid out with the same relative offsets as the struct(which is obvious, as that is the most natural way). That is all that is needed to treat the memory the static variables use as the struct in which they are part of. No need to make it any more complex than that. Every variable has an address. That includes static members of a struct. But their location has absolutely no relationship to any instance of a struct. They have a fixed location in memory. Consider: module Foo; int x; struct Bar { static int y; int z; } There is effectively no difference between x and y here. The only difference is that Bar is part of y's namespace, so you can access them like so: Foo.x; Foo.Bar.y; y's location has no relationship to any instance of Bar, and the declaration of the Bar type has no address. Of course you can take the address of y, as , but you can also take the address of x. Take y out of Bar and the only difference is that you no longer need Bar as part of the namespace. On the other hand: Bar b; writeln(b.z); As an instance of Bar, b *does* have a location in memory. And z *does* have an offset that is relative to that location. So y.offsetof does not exist, because there is no instance of Bar to which it can have a relative address.
Re: Why no offsetof for static struct?
On 07/10/2017 02:14 PM, FoxyBrown wrote: > On Monday, 10 July 2017 at 20:13:46 UTC, Adam D. Ruppe wrote: >> On Monday, 10 July 2017 at 20:01:39 UTC, FoxyBrown wrote: >>> Cannot get the offset of static members of a struct >> >> That's because static members do not have an offset. They are not part >> of the struct in memory, just in name. >> >>> We can clearly get a pointer to the static struct X >> >> There's barely any such thing as a static struct. That's just a struct >> that stands without outside context which is almost all structs, >> actually, so the term isn't special. >> >>> since is effectively the address of X(regardless nomenclature >>> and terminology issues in D trying to hide this). >> >> No, it isn't. Static members are stored in an entirely different place >> than non-static members. They are really just global variables in >> memory with their in-source name being nested somewhere else. > > > This is not true, just because there isn't any official statement, or > even if denied, does not make it true. I have proof: > > auto GetStaticAddress(T)() > { > mixin("auto p = cast(T*)"~__traits(allMembers, T)[0]~";"); > return p; > } > > > Returns the address of a struct's static members. Yes but that address is not offset from the beginning of any struct object. What would be its relationship to the following two objects? import std.stdio; auto GetStaticAddress(T)() { mixin("auto p = cast(T*)"~__traits(allMembers, T)[0]~";"); return p; } struct S { static int s; int m; } void main() { writeln("S.s is at ", GetStaticAddress!S); auto a = S(); auto b = S(); writeln("a is at ", ); writeln("b is at ", ); } Prints S.s is at 7F6D68484710 a is at 7FFEADF41B68 b is at 7FFEADF41B6C So there is no offset of S.s to speak of (i.e. number of bytes from the beginning of) neither from a nor b. > It's pretty obvious, the compiler seems to instantiate the static > members simply as a sort of "singleton". Makes sense. > They are laid out with the same > relative offsets as the struct(which is obvious, as that is the most > natural way). That is all that is needed to treat the memory the static > variables use as the struct in which they are part of. No need to make > it any more complex than that. S.s is sitting in memory all by itself without are relation to any other S members. > Just because D obfuscates that static structs have addresses, doesn't > mean they don't. I assume you mean "static members". Then, yes, of course they have addresses. And you don't even need a function like GetStaticAddress(): writeln("S.s is at ", ); > No need to perpetuate a misnomer. Static structs and > classes have addresses. Again, I think you mean "static members of" or "instances of" structs and classes. Ali
Re: Why no offsetof for static struct?
On Monday, 10 July 2017 at 20:13:46 UTC, Adam D. Ruppe wrote: On Monday, 10 July 2017 at 20:01:39 UTC, FoxyBrown wrote: Cannot get the offset of static members of a struct That's because static members do not have an offset. They are not part of the struct in memory, just in name. We can clearly get a pointer to the static struct X There's barely any such thing as a static struct. That's just a struct that stands without outside context which is almost all structs, actually, so the term isn't special. since is effectively the address of X(regardless nomenclature and terminology issues in D trying to hide this). No, it isn't. Static members are stored in an entirely different place than non-static members. They are really just global variables in memory with their in-source name being nested somewhere else. This is not true, just because there isn't any official statement, or even if denied, does not make it true. I have proof: auto GetStaticAddress(T)() { mixin("auto p = cast(T*)"~__traits(allMembers, T)[0]~";"); return p; } Returns the address of a struct's static members. It's pretty obvious, the compiler seems to instantiate the static members simply as a sort of "singleton". They are laid out with the same relative offsets as the struct(which is obvious, as that is the most natural way). That is all that is needed to treat the memory the static variables use as the struct in which they are part of. No need to make it any more complex than that. Just because D obfuscates that static structs have addresses, doesn't mean they don't. No need to perpetuate a misnomer. Static structs and classes have addresses. No, it might not be officially supported and the compiler may end up doing something funky, but it works, and works as it should, and should become part of D because it is useful: auto GetOpts(T)(string[] args) { import std.getopt, std.meta, std.traits; auto t = GetStaticAddress!(T)(); string combine() { string s = ""; foreach(m; AliasSeq!(__traits(allMembers, T))) { mixin("enum a = __traits(getAttributes, T."~m~")[0];"); mixin("s ~= \"`"~a~"`, &"~T.stringof~"."~m~", \";"); } return s; } enum s = combine(); mixin("return getopt(args, "~s~");"); } struct X { align(1): __gshared public static: @("A") bool A; @("B") string B; @("C") string[] C; }; which allows us to do GetOps!X(args) vs getop(args, "A", , "B", , "C", ); replaces the overly verbose getopt. Tell me that isn't useful and tell me that static structs don't have addresses!
Why no offsetof for static struct?
Cannot get the offset of static members of a struct struct X { __gshared public: int x; } X.x.offsetof < invalid. We can clearly get a pointer to the static struct X since is effectively the address of X(regardless nomenclature and terminology issues in D trying to hide this). e.g., auto p = cast(X*) will, for all practical purposes be a pointer to X. auto GetStaticAddress(T)() { mixin("auto p = cast(T*)"~__traits(allMembers, T)[0]~";"); return p; } Of course, assuming that the first member is at the same location as the start of the struct and the elements are laid out in the same positions(not sure if this is guaranteed, but probably is). Would be much nicer if we could just take the address of a static struct This is pretty useful for simplification: auto GetStaticAddress(T)() { mixin("auto p = cast(T*)"~__traits(allMembers, T)[0]~";"); return p; } auto GetOpts(T)(string[] args) { import std.getopt, std.meta, std.traits; auto t = GetStaticAddress!(T)(); string combine() { string s = ""; foreach(m; AliasSeq!(__traits(allMembers, T))) { mixin("enum a = __traits(getAttributes, T."~m~")[0];"); mixin("s ~= \"`"~a~"`, &"~T.stringof~"."~m~", \";"); } return s; } enum s = combine(); mixin("return getopt(args, "~s~");"); } struct X { align(1): __gshared public static: @("A") bool A; @("B") string B; @("C") string[] C; }; which allows us to do GetOps!X(args) vs getop(args, "A", , "B", , "C", ); Could be improved to only deal with special argument attributes on X's fields and allow for non-static strucs(for the general case of mapping). Sort of a map between attribute space on a type and some function.
Re: Why no offsetof for static struct?
On Monday, 10 July 2017 at 20:01:39 UTC, FoxyBrown wrote: Cannot get the offset of static members of a struct That's because static members do not have an offset. They are not part of the struct in memory, just in name. We can clearly get a pointer to the static struct X There's barely any such thing as a static struct. That's just a struct that stands without outside context which is almost all structs, actually, so the term isn't special. since is effectively the address of X(regardless nomenclature and terminology issues in D trying to hide this). No, it isn't. Static members are stored in an entirely different place than non-static members. They are really just global variables in memory with their in-source name being nested somewhere else.
Why no offsetof for static struct?
Cannot get the offset of static members of a struct struct X { __gshared public: int x; } X.x.offsetof < invalid. We can clearly get a pointer to the static struct X since is effectively the address of X(regardless nomenclature and terminology issues in D trying to hide this). e.g., auto p = cast(X*) will, for all practical purposes be a pointer to X. auto GetStaticAddress(T)() { mixin("auto p = cast(T*)"~__traits(allMembers, T)[0]~";"); return p; } Of course, assuming that the first member is at the same location as the start of the struct and the elements are laid out in the same positions(not sure if this is guaranteed, but probably is). Would be much nicer if we could just take the address of a static struct
Re: How to get the address of a static struct?
On Monday, 10 July 2017 at 03:48:17 UTC, FoxyBrown wrote: static struct S auto s = // ?!?!?! invalid because S is a struct, but... basically s = S. So S.x = s.x and s.a = S.a; Why do I have to do this? Static has a different meaning for struct. More or less it means it won't have access to a delegate/fat pointer to the function that uses it. It doesn't mean there's only 1 instantiation ever (unlike like the static variables). So static is a no-op in this case (though still syntactically legal to use). To get the address of the struct you STILL have to instantiate it first. Although you don't to in order to access it's static members. Though if all the members are static, it's basically a namespace and doing so is kinda pointless.
Re: How to get the address of a static struct?
Thread local struct: ```D module foobar; struct Foo { int x; } Foo foo = Foo(8); void main() { import std.stdio; writeln(); } ``` Global struct: ```D module foobar; struct Foo { int x; } __gshared Foo foo = Foo(8); void main() { import std.stdio; writeln(); } ``` Compile time constant: ```D module foobar; struct Foo { int x; } enum FOO = Foo(8); void main() { import std.stdio; Foo foo = FOO; writeln(); } ```
How to get the address of a static struct?
static struct S { public static: int x; string a; } auto s = // ?!?!?! invalid because S is a struct, but... basically s = S. So S.x = s.x and s.a = S.a; Why do I have to do this? Because in visual D, global structs don't show up in the debugger. So if I create a local alias, I can see see them, but I don't wanna have to do one variable for each variable in the struct...
Re: Reason for 'static struct'
Yes, exactly. Some people even use static if it is not needed because it is harmless. And remove it only when enclosing context is demand. Dne 9. 12. 2015 22:40 napsal uživatel "Jon D via Digitalmars-d-learn" < digitalmars-d-learn@puremagic.com>: > On Wednesday, 9 December 2015 at 21:23:03 UTC, Daniel Kozák wrote: > >> V Wed, 09 Dec 2015 21:10:43 + >> Jon D via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> >> napsáno: >> >> There is a fair bit of range related code in the standard library >>> structured like: >>> >>> auto MyRange(Range)(Range r) >>> if (isInputRange!Range) >>> { >>> static struct Result >>> { >>> private Range source; >>> // define empty, front, popFront, etc >>> } >>> return Result(r); >>> } >>> >>> I'm curious about what declaring the Result struct as 'static' does, and >>> if there are use cases where it be better to exclude the static qualifier. >>> >>> --Jon >>> >> >> It make it non-nested struct: https://dlang.org/spec/struct.html#nested >> > > Thanks. So, is in the example above, would the advantage be that 'static' > avoids saving the enclosing state, which is not needed? >
Re: Reason for 'static struct'
On Wednesday, 9 December 2015 at 21:23:03 UTC, Daniel Kozák wrote: V Wed, 09 Dec 2015 21:10:43 + Jon D via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> napsáno: There is a fair bit of range related code in the standard library structured like: auto MyRange(Range)(Range r) if (isInputRange!Range) { static struct Result { private Range source; // define empty, front, popFront, etc } return Result(r); } I'm curious about what declaring the Result struct as 'static' does, and if there are use cases where it be better to exclude the static qualifier. --Jon It make it non-nested struct: https://dlang.org/spec/struct.html#nested Thanks. So, is in the example above, would the advantage be that 'static' avoids saving the enclosing state, which is not needed?
Reason for 'static struct'
There is a fair bit of range related code in the standard library structured like: auto MyRange(Range)(Range r) if (isInputRange!Range) { static struct Result { private Range source; // define empty, front, popFront, etc } return Result(r); } I'm curious about what declaring the Result struct as 'static' does, and if there are use cases where it be better to exclude the static qualifier. --Jon
Re: Reason for 'static struct'
V Wed, 09 Dec 2015 21:10:43 + Jon D via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> napsáno: > There is a fair bit of range related code in the standard library > structured like: > > auto MyRange(Range)(Range r) > if (isInputRange!Range) > { > static struct Result > { > private Range source; > // define empty, front, popFront, etc > } > return Result(r); > } > > I'm curious about what declaring the Result struct as 'static' > does, and if there are use cases where it be better to exclude > the static qualifier. > > --Jon It make it non-nested struct: https://dlang.org/spec/struct.html#nested
Re: static class vs. static struct
On Monday, 26 January 2015 at 14:02:54 UTC, ref2401 wrote: What's the difference between static class and static struct? What should i use? In simple words, Singleton is a pattern and not a keyword. The Singleton pattern has several advantages over static classes. A singleton allows a class for which there is just one, persistent instance across the lifetime of an application. That means, it created a single instance and that instance (reference to that instance) can be passed as a parameter to other methods, and treated as a normal object. While a static class allows only static methods and and you cannot pass static class as parameter. Full Source: http://net-informations.com/faq/netfaq/singlestatic.htm Vyar
Re: static class vs. static struct
In simple words, Singleton is a pattern and not a keyword. The Singleton pattern has several advantages over static classes. A singleton allows a class for which there is just one, persistent instance across the lifetime of an application. That means, it created a single instance and that instance (reference to that instance) can be passed as a parameter to other methods, and treated as a normal object. While a static class allows only static methods and and you cannot pass static class as parameter. More about. http://net-informations.com/faq/netfaq/singlestatic.htm Lee
Re: static class vs. static struct
On 01/27/2015 08:58 AM, Piotrek wrote: Nice list. :) 1. static variable struct A{int a} // no static before declaration static A s; //note that static is used for struct variable storage class (lifetime) static int b; etc. 2. static declaration static struct A{int a}; //static used for context unnesting static int fun(){}; // static used also for removing scope context Of course that includes static member functions, where the 'this' pointer is removed. Actually, static opCall is kind of different because it makes the type itself callable. etc. 3. static if static if(compile_time_cond) { //this section of code will be taken into the binary, used for meta programming } Another use of 'static' that means at compile time: static assert 4. Module initialization and deinitialization: static this shared static this static ~this shared static ~this 5. Module import: static import std.stdio; Ali
Re: static class vs. static struct
On 01/27/2015 08:33 AM, Piotrek wrote: Non-static means nested. Hmm,this can be misleading. Nesting in structs doesn't introduce context pointer. You must be thinking of structs nested inside user-defined types. Structs that are nested inside functions do have the context pointer. Ali
Re: static class vs. static struct
For several times I've met struct(or static struct) usage in Phobos for singleton pattern implementation. Unfortunately now i can remember only core.runtime.Runtime. So I've got a question. Why do Phobos guys use struct or static struct for or singleton pattern implementation? Why don't use static final class for this purpose?
Re: static class vs. static struct
On Tuesday, 27 January 2015 at 09:01:39 UTC, ref2401 wrote: For several times I've met struct(or static struct) usage in Phobos for singleton pattern implementation. Unfortunately now i can remember only core.runtime.Runtime. So I've got a question. Why do Phobos guys use struct or static struct for or singleton pattern implementation? Why don't use static final class for this purpose? I do not think this is a singleton pattern (no instance). I see it much more like namespace in case of core.runtime.Runtime. And yes static final class could do that too but struct looks better than final class and you can disable this on structs
Re: static class vs. static struct
On Tue, 27 Jan 2015 09:40:08 +, Daniel Kozak wrote: import std.stdio; import std.conv; struct S { @disable this(); } final class C { } void main() { writeln(C.sizeof); writeln(S.sizeof); } blind guess: vmt with toString() from Object? ;-) signature.asc Description: PGP signature
Re: static class vs. static struct
On Tuesday, 27 January 2015 at 09:36:49 UTC, Daniel Kozak wrote: On Tuesday, 27 January 2015 at 09:01:39 UTC, ref2401 wrote: For several times I've met struct(or static struct) usage in Phobos for singleton pattern implementation. Unfortunately now i can remember only core.runtime.Runtime. So I've got a question. Why do Phobos guys use struct or static struct for or singleton pattern implementation? Why don't use static final class for this purpose? I do not think this is a singleton pattern (no instance). I see it much more like namespace in case of core.runtime.Runtime. And yes static final class could do that too but struct looks better than final class and you can disable this on structs import std.stdio; import std.conv; struct S { @disable this(); } final class C { } void main() { writeln(C.sizeof); writeln(S.sizeof); }
Re: static class vs. static struct
On Tuesday, 27 January 2015 at 18:24:29 UTC, Ali Çehreli wrote: On 01/27/2015 08:33 AM, Piotrek wrote: Non-static means nested. Hmm,this can be misleading. Nesting in structs doesn't introduce context pointer. You must be thinking of structs nested inside user-defined types. Structs that are nested inside functions do have the context pointer. Ali What you wrote about the structs is true. However I was referring to other thing. I just wanted to emphasize (with my poor English) that also classes and structs *nested in struct* doesn't contain the additional context pointer. As opposed to class nested in class. Then I think we'd better not say that non-static means nested. Piotrek
Re: static class vs. static struct
On Tuesday, 27 January 2015 at 18:18:02 UTC, Ali Çehreli wrote: On 01/27/2015 08:58 AM, Piotrek wrote: Nice list. :) 1. static variable struct A{int a} // no static before declaration static A s; //note that static is used for struct variable storage class (lifetime) static int b; etc. 2. static declaration static struct A{int a}; //static used for context unnesting static int fun(){}; // static used also for removing scope context Of course that includes static member functions, where the 'this' pointer is removed. Actually, static opCall is kind of different because it makes the type itself callable. etc. 3. static if static if(compile_time_cond) { //this section of code will be taken into the binary, used for meta programming } Another use of 'static' that means at compile time: static assert 4. Module initialization and deinitialization: static this shared static this static ~this shared static ~this 5. Module import: static import std.stdio; Ali Thanks for comments, Mr. Professor. On duty as usual ;) Let me here thank for your book which I've been reading for some time. Piotrek
Re: static class vs. static struct
On 01/27/2015 01:33 PM, Piotrek wrote: On Tuesday, 27 January 2015 at 18:24:29 UTC, Ali Çehreli wrote: On 01/27/2015 08:33 AM, Piotrek wrote: Non-static means nested. Hmm,this can be misleading. Nesting in structs doesn't introduce context pointer. Oh, I misread what you wrote. Sorry... classes and structs *nested in struct* doesn't contain the additional context pointer. As opposed to class nested in class. Then I think we'd better not say that non-static means nested. Piotrek Makes sense. Ali
Re: static class vs. static struct
On 01/27/2015 01:44 PM, Piotrek wrote: Let me here thank for your book I am glad that it is useful. which I've been reading for some time. Me too! I browsed the index section to remember the other uses of 'static'. :) Ali
Re: static class vs. static struct
On 01/27/15 10:40, Daniel Kozak via Digitalmars-d-learn wrote: On Tuesday, 27 January 2015 at 09:36:49 UTC, Daniel Kozak wrote: On Tuesday, 27 January 2015 at 09:01:39 UTC, ref2401 wrote: For several times I've met struct(or static struct) usage in Phobos for singleton pattern implementation. Unfortunately now i can remember only core.runtime.Runtime. So I've got a question. Why do Phobos guys use struct or static struct for or singleton pattern implementation? Why don't use static final class for this purpose? I do not think this is a singleton pattern (no instance). I see it much more like namespace in case of core.runtime.Runtime. And yes static final class could do that too but struct looks better than final class and you can disable this on structs import std.stdio; import std.conv; struct S { @disable this(); } final class C { } void main() { writeln(C.sizeof); writeln(S.sizeof); } D's `class` magically adds a level of indirection, so C.sizeof gives you just the size of the _reference_. For the true (ie instance/payload) size you'd have to use __traits(classInstanceSize, C) artur
Re: static class vs. static struct
On Tuesday, 27 January 2015 at 09:01:39 UTC, ref2401 wrote: For several times I've met struct(or static struct) usage in Phobos for singleton pattern implementation. Unfortunately now i can remember only core.runtime.Runtime. So I've got a question. Why do Phobos guys use struct or static struct for or singleton pattern implementation? Why don't use static final class for this purpose? You probably saw static member function. Please take the following with a big grain of salt as I took it out of my head: We can divide the D static keyword usage into 3 types: 1. static variable struct A{int a} // no static before declaration static A s; //note that static is used for struct variable storage class (lifetime) static int b; etc. 2. static declaration static struct A{int a}; //static used for context unnesting static int fun(){}; // static used also for removing scope context etc. 3. static if static if(compile_time_cond) { //this section of code will be taken into the binary, used for meta programming } I don't think there is much (if any) use of static (type 1) for singleton. Piotrek
Re: static class vs. static struct
On Monday, 26 January 2015 at 21:55:19 UTC, anonymous wrote: On Monday, 26 January 2015 at 21:33:10 UTC, Piotrek wrote: On Monday, 26 January 2015 at 14:11:32 UTC, bearophile wrote: Non-static structs/classes have an extra pointer. Bye, bearophile Since when structs have an extra pointer? Maybe you are talking about nested structs? Non-static means nested. Hmm,this can be misleading. Nesting in structs doesn't introduce context pointer. But I agree that if we take into account a hypothetical inferred static attribute for nesting in struct and the module scope cases, then the static and non-static classification looks the most suitable. Piotrek
static class vs. static struct
What's the difference between static class and static struct? What should i use?
Re: static class vs. static struct
On Monday, 26 January 2015 at 14:02:54 UTC, ref2401 wrote: What's the difference between static class and static struct? What should i use? Non-static structs/classes have an extra pointer. Static ones don't have it, so their differences are the usual ones: a class is used by reference and they are often on the heap, while a struct is handled by value (or pointer to value). A class has two extra hidden fields. Bye, bearophile
Re: static class vs. static struct
On Monday, 26 January 2015 at 21:33:10 UTC, Piotrek wrote: On Monday, 26 January 2015 at 14:11:32 UTC, bearophile wrote: Non-static structs/classes have an extra pointer. Bye, bearophile Since when structs have an extra pointer? Maybe you are talking about nested structs? Non-static means nested.
Re: static class vs. static struct
On Monday, 26 January 2015 at 14:11:32 UTC, bearophile wrote: Non-static structs/classes have an extra pointer. Bye, bearophile Since when structs have an extra pointer? Maybe you are talking about nested structs? Piotrek
Re: static struct definition
On Monday, 27 August 2012 at 18:53:23 UTC, bearophile wrote: Andrej Mitrovic: Isn't this limited to just classes? See the last section of this page: http://dlang.org/struct.html Nested Structs: A nested struct is a struct that is declared inside the scope of a function or a templated struct that has aliases to local functions as a template argument. Nested structs have member functions. It has access to the context of its enclosing scope (via an added hidden field). Bye, bearophile From TDPL: 7.18: Unlike classes nested within classes, nested structs and nested classes within structs don’t contain any hidden member outer—there is no special code generated. The main design goal of nesting such types is to enforce the desired access control. I suppose this has become obsolete then? ...Or is it the other way around?
Re: static struct definition
On Tue, 28 Aug 2012 12:10:47 +0200, monarch_dodra monarchdo...@gmail.com wrote: From TDPL: 7.18: Unlike classes nested within classes, nested structs and nested classes within structs don’t contain any hidden member outer—there is no special code generated. The main design goal of nesting such types is to enforce the desired access control. I suppose this has become obsolete then? ...Or is it the other way around? TDPL trumps most everything else, I believe. -- Simen
Re: static struct definition
On Tuesday, 28 August 2012 at 11:06:51 UTC, Simen Kjaeraas wrote: On Tue, 28 Aug 2012 12:10:47 +0200, monarch_dodra monarchdo...@gmail.com wrote: From TDPL: 7.18: Unlike classes nested within classes, nested structs and nested classes within structs don’t contain any hidden member outer—there is no special code generated. The main design goal of nesting such types is to enforce the desired access control. I suppose this has become obsolete then? ...Or is it the other way around? TDPL trumps most everything else, I believe. Well, at the same time, the reason I asked is because Andrei told me to declare a sub-struct as static in one of my pull requests. Given he's the author of TDPL... Anyways, I'll try to bring him into the conversation from.
static struct definition
What exactly does it mean when you put static in front of a struct _definition_ (not instance) ? EG: static struct S { static struct SS { } } As opposed to struct S { struct SS { } }
Re: static struct definition
monarch_dodra: What exactly does it mean when you put static in front of a struct _definition_ (not instance) ? EG: static struct S { static struct SS { } } As opposed to struct S { struct SS { } } For the outer struct S I think it means nothing, it's just the stupid DMD compiler that accepts random qualifiers and attributes. void foo() { static void bar() {} struct struct Spam {} struct Baz {} Baz baz; // static assert(Baz.sizeof == size_t.sizeof); } For the inner structs like Spam it's supposed to mean something. Just like static inner functions like bar() can't refer to variables from the enclosing function, static structs like Spam are like global structs, it's just their name that is visible inside the enclosing function foo. Truly inner structs like Baz should have a hidden pointer field that points to the enclosing struct. In practice I don't remember if this feature is already present in the D front-end. Bye, bearophile
Re: static struct definition
On 8/27/12, bearophile bearophileh...@lycos.com wrote: Truly inner structs like Baz should have a hidden pointer field that points to the enclosing struct. Isn't this limited to just classes?
Re: static struct definition
Andrej Mitrovic: Isn't this limited to just classes? See the last section of this page: http://dlang.org/struct.html Nested Structs: A nested struct is a struct that is declared inside the scope of a function or a templated struct that has aliases to local functions as a template argument. Nested structs have member functions. It has access to the context of its enclosing scope (via an added hidden field). Bye, bearophile
Static struct assign
While trying to create a safe int, I have found a problem, this is reduced code: struct Foo { int x; static Foo opAssign(int value) { return Foo(value); } } void main() { Foo y = 0; } The compiler prints: test.d(6): Error: cannot implicitly convert expression (0) of type int to Foo While this generates no error: Foo y; y = 0; is OK. Do you know if there is a way to do that? Bye and thank you, bearophile
Re: Static struct assign
On 03/11/2010 11:22 AM, bearophile wrote: While trying to create a safe int, I have found a problem, this is reduced code: struct Foo { int x; static Foo opAssign(int value) { return Foo(value); } } void main() { Foo y = 0; } The compiler prints: test.d(6): Error: cannot implicitly convert expression (0) of type int to Foo While this generates no error: Foo y; y = 0; is OK. Do you know if there is a way to do that? Bye and thank you, bearophile define opCall in Foo
Static struct assign
DMD 1.026 used by Codepad used to give errors on this code: http://codepad.org/QSE36vhJ struct S { int x; } void main() { S i = 5; printf(%d, i.x); // prints 0 } But the current DMD/LDC give no compilation error and just print 0. Is this a new bug in the front-end? Bye, bearophile