Re: Why dtor are not executed when removing a struct from associative arrays?
On 9/20/21 8:23 AM, Learner wrote: I was expecting something like going out of scope for that ```d import std.stdio; struct S { ~this() { writeln("S is being destructed"); } } void main() { S[int] aa; aa[1] = S(); aa.remove(1); writeln("Why no dtor call on remove?"); } ``` I was expecting S instance dtor called S is being destructed AA values are not destroyed on removal. For a simple reason -- someone might still be referencing it. ```d struct S { int x; } void main() { S[int] aa; aa[1] = S(5); auto sptr = 1 in aa; sptr.x = 6; assert(aa[1].x == 6); aa.remove(1); assert(sptr.x == 6; } ``` -Steve
Re: Why dtor are not executed when removing a struct from associative arrays?
On Monday, 20 September 2021 at 13:48:01 UTC, Tejas wrote: On Monday, 20 September 2021 at 12:23:00 UTC, Learner wrote: [...] I think it *is* being called: ```d import std.stdio; struct S { int a; this(int param){ a = param; } ~this() { writeln("S(",a,") is being destructed"); } } void main() { S[int] aa; aa[1] = S(5); aa.remove(1); aa[1] = S(10); //writeln("Why no dtor call on remove?"); } Output: S(5) is being destructed S(10) is being destructed ``` If the destructors were being executed based on the ending of scope, `S(10)` would have been destroyed first. Oh dear, I made a mistake :( Sorry, shouldn't have commented out the `writeln`
Re: How to do "C++ classes"?
On Monday, 20 September 2021 at 15:56:44 UTC, Ferhat Kurtulmuş wrote: On Monday, 20 September 2021 at 15:45:08 UTC, Adam D Ruppe wrote: On Monday, 20 September 2021 at 15:35:02 UTC, Ferhat Kurtulmuş wrote: I thought it's stack-allocated and scoped. It is. But when I try to return a class instance from a function, it still works? dmd only makes that an error if you specify `@safe` and i think `-dip1000`. Try adding one or both of those and recompiling and see what happens. Note that even if the compiler doesn't error on it, it is undefined behavior to return the stack reference so be sure to treat it right. That is what I thought too. I only tried this on the online compiler. Thank you. Have a great day or night captain. I also think this is a dirty corner of the complier since it must raise an error for scoped instances of classes.
Why dtor are not executed when removing a struct from associative arrays?
I was expecting something like going out of scope for that ```(D) import std.stdio; struct S { ~this() { writeln("S is being destructed"); } } void main() { S[int] aa; aa[1] = S(); aa.remove(1); writeln("Why no dtor call on remove?"); } I was expecting S instance dtor called S is being destructed ```
Re: How to do "C++ classes"?
On Saturday, 18 September 2021 at 22:16:32 UTC, Adam D Ruppe wrote: On Saturday, 18 September 2021 at 15:38:38 UTC, rempas wrote: I'm seeing in the page about "BeterC" and in the part about the [retained features](https://dlang.org/spec/betterc.html#retained), the #11 says about "COM classes and C++ classes". What are the "C++ classes"? I tried to create a class using "extern(C++)" but this didn't worked. Can someone make an example on that? extern(C++) class Foo {} void main() { scope Foo foo = new Foo(); } I thought it's stack-allocated and scoped. But when I try to return a class instance from a function, it still works? Captain Adam I need an explanation please.
Re: How to do "C++ classes"?
On Monday, 20 September 2021 at 15:35:02 UTC, Ferhat Kurtulmuş wrote: I thought it's stack-allocated and scoped. It is. But when I try to return a class instance from a function, it still works? dmd only makes that an error if you specify `@safe` and i think `-dip1000`. Try adding one or both of those and recompiling and see what happens. Note that even if the compiler doesn't error on it, it is undefined behavior to return the stack reference so be sure to treat it right.
Re: Why dtor are not executed when removing a struct from associative arrays?
On Monday, 20 September 2021 at 12:23:00 UTC, Learner wrote: I was expecting something like going out of scope for that ```(D) import std.stdio; struct S { ~this() { writeln("S is being destructed"); } } void main() { S[int] aa; aa[1] = S(); aa.remove(1); writeln("Why no dtor call on remove?"); } I was expecting S instance dtor called S is being destructed ``` I think it *is* being called: ```d import std.stdio; struct S { int a; this(int param){ a = param; } ~this() { writeln("S(",a,") is being destructed"); } } void main() { S[int] aa; aa[1] = S(5); aa.remove(1); aa[1] = S(10); //writeln("Why no dtor call on remove?"); } Output: S(5) is being destructed S(10) is being destructed ``` If the destructors were being executed based on the ending of scope, `S(10)` would have been destroyed first.
zsh: command not found: rdmd
Enter dmd lk01.d in vscode, the terminal displays zsh: command not found: dmd, an error is reported, I don't know what the problem is, can it only be run in /Users/mac1094/dmd2/osx/bin?
Cannot Instantiate SumType
I'm experiencing an error when instantiating `SumType` with an aggregate template that itself is instantiated with a void function. In other words... ```d struct Foo(alias f) {} // As the error implies, altering it to be non-void makes everything copacetic~ void bar() {} alias S = SumType!(Foo!bar); ``` The error in question... ``` Error: variable `std.typecons.ReplaceTypeUnless!(isSumTypeInstance, This, SumType!(Foo!(bar)), Foo!(bar)).F!(bar).replaceTemplateArgs` type `void` is inferred from initializer `bar()`, and variables cannot be of type `void` ``` Perhaps I'm dong something stupid, or failing to realize, because all the glue sniffing I did when I was younger has finally manifested itself, but if it's not, is there a workaround?
Re: Program crash: GC destroys an object unexpectedly
On Sunday, 19 September 2021 at 21:10:16 UTC, eugene wrote: I rearranged the code of main() like this: Similar rearrangement fixed the echo-client as well. (I moved creation of Stopper to the very beginning of main())
Re: Why dtor are not executed when removing a struct from associative arrays?
On Monday, 20 September 2021 at 14:03:09 UTC, Tejas wrote: On Monday, 20 September 2021 at 13:48:01 UTC, Tejas wrote: On Monday, 20 September 2021 at 12:23:00 UTC, Learner wrote: [...] I think it *is* being called: ```d import std.stdio; struct S { int a; this(int param){ a = param; } ~this() { writeln("S(",a,") is being destructed"); } } void main() { S[int] aa; aa[1] = S(5); aa.remove(1); aa[1] = S(10); //writeln("Why no dtor call on remove?"); } Output: S(5) is being destructed S(10) is being destructed ``` If the destructors were being executed based on the ending of scope, `S(10)` would have been destroyed first. Oh dear, I made a mistake :( Sorry, shouldn't have commented out the `writeln` To make up for my mistake: In case you still want to delete stuff deterministically despite what Steve said, I suggest you make your `struct` a reference and use `core.memory.__delete`(not recommended to use this carelessly, btw) ```d import std.stdio; import core.memory:__delete; struct S { int a; this(int param){ a = param; } ~this() { writeln("S(",a,") is being destructed"); } } void absoluteRemove(AA, keyType)(AA assArray, keyType key){ __delete(assArray[key]); } void main() { S*[int] aa; aa[1] = new S(5); absoluteRemove(aa, 1); aa[2] = new S(10); absoluteRemove(aa, 2); writeln("Why no dtor call on remove?"); } Output: S(5) is being destructed S(10) is being destructed Why no dtor call on remove? ``` Because `__delete` cannot work on stack allocated objects
Re: Cannot Instantiate SumType
On Monday, 20 September 2021 at 11:21:28 UTC, surlymoor wrote: The error in question... ``` Error: variable `std.typecons.ReplaceTypeUnless!(isSumTypeInstance, This, SumType!(Foo!(bar)), Foo!(bar)).F!(bar).replaceTemplateArgs` type `void` is inferred from initializer `bar()`, and variables cannot be of type `void` ``` Looks like this is a bug in `ReplaceType`: ```d import std.typecons; struct Foo(alias f) {} void bar() {} alias _ = ReplaceType!(int, int, Foo!bar); ``` I've submitted a bug report here: https://issues.dlang.org/show_bug.cgi?id=22325 [1]: https://phobos.dpldocs.info/std.typecons.ReplaceType.html
Re: How to do "C++ classes"?
On Monday, 20 September 2021 at 15:45:08 UTC, Adam D Ruppe wrote: On Monday, 20 September 2021 at 15:35:02 UTC, Ferhat Kurtulmuş wrote: I thought it's stack-allocated and scoped. It is. But when I try to return a class instance from a function, it still works? dmd only makes that an error if you specify `@safe` and i think `-dip1000`. Try adding one or both of those and recompiling and see what happens. Note that even if the compiler doesn't error on it, it is undefined behavior to return the stack reference so be sure to treat it right. That is what I thought too. I only tried this on the online compiler. Thank you. Have a great day or night captain.
type in extern declaration
How do I write the type of a function so as to alias it, and use that in an extern(C) declaration? For example, how do I write the type of an external function int main2(int argc, char** argv) { // } ? This is not int function(int, char**) because this is the type of a function pointer of the right type, not the type of the function itself. If I had that type aliased to mainfunc I could write extern(C) mainfunc main2; in D source to arrange to call it, and similarly any other functions of the same type.
Re: type in extern declaration
On Monday, 20 September 2021 at 20:02:24 UTC, NonNull wrote: How do I write the type of a function so as to alias it, and use that in an extern(C) declaration? For example, how do I write the type of an external function int main2(int argc, char** argv) { // } You can create an alias to the type: ```d alias MainFunc = int(int, char**); ``` However, you can't use that alias to declare a variable, because variables are not allowed to have function types: ```d MainFunc main; // Error: variable `main` cannot be declared to be a function ``` The only way you can declare a function in D is with a [function declaration.][1] [1]: https://dlang.org/spec/function.html#FuncDeclaration
Re: Why dtor are not executed when removing a struct from associative arrays?
On Monday, 20 September 2021 at 12:23:00 UTC, Learner wrote: I was expecting something like going out of scope for that ```(D) import std.stdio; struct S { ~this() { writeln("S is being destructed"); } } void main() { S[int] aa; aa[1] = S(); aa.remove(1); writeln("Why no dtor call on remove?"); } I was expecting S instance dtor called S is being destructed ``` This looks to me like a bug, as ```d import core.memory : GC; GC.collect; ``` immediately after the `.remove` will call the struct's destructor. I only see https://issues.dlang.org/show_bug.cgi?id=20379 as related, though. Here's another workaround: ```d alias purge = (kv, k) { kv[k] = typeof(kv[k]).init; kv.remove(k); }; ``` with the same caveat of the `.init` structs also getting destructed later, you can use that in place of `.remove`.
Scope with owner types
I have made an owner type that wraps malloc'd pointers with custom destroy functions from a C library and utilizes `RefCounted` for safety. I would like to be able to use the owner type `Memory` implicitly as its underlying pointer type via `alias this`. ``` struct Memory(T, alias destroy) if(!isPointer!T && isSomeFunction!destroy) { @safe: /// Pointer Wrapper struct Ptr { /// data pointer T * ptr; /// no copying this as that could result /// in premature destruction @disable this(this); /// destroy ~this() @trusted { /// if destroy function return is void /// just destroy /// else if int /// destroy then check return value /// else don't compile static if(is(ReturnType!destroy == void)) destroy(this.ptr); else static if(is(ReturnType!destroy == int)) { auto success = destroy(this.ptr); if(!success) hts_log_error(__FUNCTION__,"Couldn't destroy "~T.stringof~" * data using function "~destroy.stringof); }else{ static assert(0, "Memory doesn't recognize destroy function return type"); } } } /// reference counted Ptr RefCounted!(Ptr, RefCountedAutoInitialize.yes) rcPtr; /// get underlying data pointer /// copied from RefCounted implementation @property nothrow pure @nogc ref inout(T*) getPtr() inout return { return rcPtr.refCountedPayload.ptr; } /// allow Memory to be used as /// underlying ptr type alias getPtr this; /// ctor from raw pointer this(T * rawPtr) @trusted { auto wrapped = Ptr(rawPtr); move(wrapped,this.rcPtr.refCountedPayload); } } ``` With `alias this` I can use `auto rc = Memory!(ctype, ctype_destroy)(ctype_init());` (where `ctype_destroy` and `ctype_init` are C bindings) and then `ctype * ptr = rc;`. This is great since I can pass `rc` directly to c functions that accept `ctype *`. But how do I either: ensure `rc` stays in scope or have compile-time protection against escaping `ptr` past the lifetime of `rc`. Is this possible with either `scope` or `@live`? Could I add attributes to the C bindings to help with this?
Re: Why dtor are not executed when removing a struct from associative arrays?
On 9/20/21 5:23 AM, Learner wrote: I was expecting S instance dtor called S is being destructed If you are sure the element can be destroyed, you can call destroy(): import std.stdio; enum someSpecialInitValue = 777; struct S { int i = someSpecialInitValue; this(int i) { this.i = i; } ~this() { writeln("S with ", i, " is being destructed"); } } void destroyAndRemove(AA, Key)(AA aa, Key key) { auto found = key in aa; if (found) { destroy(*found); aa.remove(key); } } void main() { S[int] aa; aa[1] = S(1); aa.destroyAndRemove(1); writeln("Actually, 2 dtor calls! :)"); } destroy() puts the object to its initial state, which means, it gets destroyed again. That's why there are two destructor calls below for the same object. I used a special value to demonstrate the second destructor is called on the init state: S with 1 is being destructed Actually, 2 dtor calls! :) S with 777 is being destructed Ali
Re: Why dtor are not executed when removing a struct from associative arrays?
On 9/20/21 10:22 AM, Tejas wrote: In case you still want to delete stuff deterministically despite what Steve said, I suggest you make your `struct` a reference and use `core.memory.__delete`(not recommended to use this carelessly, btw) Do not call `__delete` here, use `destroy`. `__delete` will attempt to deallocate the block, which likely will fail since the key comes before the value, and GC.free on an interior pointer (I think) fails. But if it succeeded, it would not be good. This leaves a dangling pointer inside the AA. Rehashing the AA likely would result in a memory corruption. If you use destroy, the destructor will be called by the GC as well, but a struct should properly handle destroying the .init value. -Steve
Re: zsh: command not found: rdmd
On Monday, 20 September 2021 at 11:04:42 UTC, leikang wrote: Enter dmd lk01.d in vscode, the terminal displays zsh: command not found: dmd, an error is reported, I don't know what the problem is, can it only be run in /Users/mac1094/dmd2/osx/bin? How have you installed dmd?
Re: Templates for instantiating derived class
On Monday, 20 September 2021 at 22:16:47 UTC, rjkilpatrick wrote: auto opBinary(string op)(int rhs) const if (op == "+") { return new Super(_a + rhs); // Creates of type Super even when called from derived class } Make this auto opBinary(string op, this This)(int rhs) . return new This(_a + rhs); } The template this param is the static type it is called on. https://dlang.org/spec/template.html#template_this_parameter Note though that this is the static type. If you do Super thing = new Derived(); thing + 5; it will still return Super since that's the type it was called through. If you want it to actually return derived, you'll have to add a virtual factory function: class Super { protected Super factory() { return new Super(); } } class Derived : Super { override Derived factory() { return new Derived(); } } Then you can call obj.factory to get the right dynamic type. (forward args as needed etc.) Some kind of `return new this(...)` would be good, but that's not possible. You can do `return new typeof(this)(...);` fyi but it is again the static type of this, which will be whatever it is where it is defined. This is a useful trick if you were to make that factory function a mixin template or something though.
Re: zsh: command not found: rdmd
On Monday, 20 September 2021 at 21:51:32 UTC, russhy wrote: On Monday, 20 September 2021 at 11:04:42 UTC, leikang wrote: Enter dmd lk01.d in vscode, the terminal displays zsh: command not found: dmd, an error is reported, I don't know what the problem is, can it only be run in /Users/mac1094/dmd2/osx/bin? How have you installed dmd? I downloaded and installed it on my Mac, installed it under the local disk, and then entered the /Users/mac1094/dmd2/osx/bin directory to enter dmd xxx.d to run
Re: Cannot Instantiate SumType
On Monday, 20 September 2021 at 15:33:23 UTC, Paul Backus wrote: On Monday, 20 September 2021 at 11:21:28 UTC, surlymoor wrote: The error in question... ``` Error: variable `std.typecons.ReplaceTypeUnless!(isSumTypeInstance, This, SumType!(Foo!(bar)), Foo!(bar)).F!(bar).replaceTemplateArgs` type `void` is inferred from initializer `bar()`, and variables cannot be of type `void` ``` Looks like this is a bug in `ReplaceType`: ```d import std.typecons; struct Foo(alias f) {} void bar() {} alias _ = ReplaceType!(int, int, Foo!bar); ``` I've submitted a bug report here: https://issues.dlang.org/show_bug.cgi?id=22325 [1]: https://phobos.dpldocs.info/std.typecons.ReplaceType.html Thanks, Paul. Glad to see the fix is simple.
How to make clang use a different tk framework version on MacOS?
My tkd GUI app started getting compiled with an outdated 8.5 Tk framework version which gets shipped with command line tools: `xcode-select --install`. As a result, the UI doesn't display icons and is laggy. When you run the compiled tk app, you get a notorious warning: ``` DEPRECATION WARNING: The system version of Tk is deprecated and may be removed in a future release. Please don't rely on it. Set TK_SILENCE_DEPRECATION=1 to suppress this warning. ``` This didn't happen before but here is why it probably started to occur. I've recently been playing with uninstalling the MacPorts in favour of homebrew and in the process I had to remove tk8.6 library which was installed once by MacPorts. I wasn't aware that command line tools come with their own version of tk which is 8.5. Somehow, after moving to homebrew, I rebuilt the app and saw new warnings that never appeared before: ``` ../../../../.dub/packages/tkd-1.1.13/tkd/source/tkd/image/png.d(83,7): Deprecation: Function `tkd.image.image.Image.embedBase64Data!("lock.png", EmbeddedPng!"lock.png").embedBase64Data` of type `@system EmbeddedPng!"lock.png"()` is not accessible from module `png` ``` I tried coming back to MacPorts, reinstalling the command line tools reinstalling the tkd and dub dependencies but nothing worked so far. Maybe someone here has experience how to make clang go and link against the tk 8.6 version installed by MacPorts instead of 8.5. That would be of great help.
Re: Templates for instantiating derived class
On 9/20/21 6:16 PM, rjkilpatrick wrote: Essentially, I would like to write a template that calls the constructor of the parent class or the constructor of the inherited class, depending on its type. ... Some kind of `return new this(...)` would be good, but that's not possible. I think it has to be done with templates, but I'm not sure how to do this. Any help would be greatly appreciated. What you want is to change that operator into a virtual function. Yes, you still have to write the overrides, but you could if you want use a mixin. Adam's solution works, but only uses the static type. ```d class Super { private int _a; this(){} this(int a) { _a = a; } Super performAdd(int rhs) const { return new Super(_a + rhs); } alias opBinary(string op : "+") = performAdd; } class Derived : Super { this(){} this(int a) { _a = a + 1; } override Derived performAdd(int rhs) { return new Derived(_a + rhs); } } void main() { import std : writeln; Super foo = new Super(1); Super foo2 = foo + 1; // Works fine as calls `Super` constructor Derived bar = new Derived(2); Derived bar2 = bar + 1; // works now Super b2 = bar; Derived d2 = cast(Derived)(b2 + 1); // ok, *and* calls Derive's version of performAdd assert(d2 !is null && d2._a == bar2._a); } ```
Re: zsh: command not found: rdmd
On Monday, 20 September 2021 at 11:04:42 UTC, leikang wrote: Enter dmd lk01.d in vscode, the terminal displays zsh: command not found: dmd, an error is reported, I don't know what the problem is, can it only be run in /Users/mac1094/dmd2/osx/bin? Keep in mind that if you have M1 machine, you cannot use dmd. Download and use `ldc2` compiler for arm64 here. https://github.com/ldc-developers/ldc/releases/download/v1.27.1/ldc2-1.27.1-osx-arm64.tar.xz
Templates for instantiating derived class
Essentially, I would like to write a template that calls the constructor of the parent class or the constructor of the inherited class, depending on its type. ```d #!/usr/bin/env dub /+ dub.sdl: name "mwe" +/ class Super { private int _a; this(){} this(int a) { _a = a; } auto opBinary(string op)(int rhs) const if (op == "+") { return new Super(_a + rhs); // Creates of type Super even when called from derived class } } class Derived : Super { this(){} this(int a) { _a = a + 1; } } void main() { import std : writeln; Super foo = new Super(1); Super foo2 = foo + 1; // Works fine as calls `Super` constructor Derived bar = new Derived(2); Derived bar2 = bar + 1; // Cannot implicitly cast `Super` to `Derived` } ``` Some kind of `return new this(...)` would be good, but that's not possible. I think it has to be done with templates, but I'm not sure how to do this. Any help would be greatly appreciated.
Re: type in extern declaration
On Monday, 20 September 2021 at 20:02:24 UTC, NonNull wrote: How do I write the type of a function so as to alias it, and use that in an extern(C) declaration? For example, how do I write the type of an external function int main2(int argc, char** argv) { // } ? This is not int function(int, char**) because this is the type of a function pointer of the right type, not the type of the function itself. If I had that type aliased to mainfunc I could write extern(C) mainfunc main2; in D source to arrange to call it, and similarly any other functions of the same type. This is for C++, but I think you'll find it helpful all the same https://atilaoncode.blog/2019/03/07/the-joys-of-translating-cs-stdfunction-to-d/
Re: zsh: command not found: rdmd
On Tuesday, 21 September 2021 at 01:02:30 UTC, leikang wrote: On Monday, 20 September 2021 at 21:51:32 UTC, russhy wrote: On Monday, 20 September 2021 at 11:04:42 UTC, leikang wrote: Enter dmd lk01.d in vscode, the terminal displays zsh: command not found: dmd, an error is reported, I don't know what the problem is, can it only be run in /Users/mac1094/dmd2/osx/bin? How have you installed dmd? I downloaded and installed it on my Mac, installed it under the local disk, and then entered the /Users/mac1094/dmd2/osx/bin directory to enter dmd xxx.d to run Does it work when you go to that `/Users/mac1094/dmd2/osx/bin` location or write `/Users/mac1094/dmd2/osx/bin 1k01.d`? Then you just have to add the location of dmd to your path How to do that? Idk, I use windows/linux