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: I do not understand copy constructors
On Thursday, 12 August 2021 at 16:12:39 UTC, Paul Backus wrote: On Thursday, 12 August 2021 at 15:39:40 UTC, Learner wrote: [...] You have forgotten to add a member variable of type `A` to your `B` struct. If you add one, you will see the following error message: [...] "implicit conversions are not allowed for arguments passed to `ref` parameters" was the point missing to me. Good to know, and thank yo to everyone!
Re: I do not understand copy constructors
On Thursday, 12 August 2021 at 15:50:05 UTC, Tejas wrote: On Thursday, 12 August 2021 at 15:39:40 UTC, Learner wrote: On Thursday, 12 August 2021 at 14:57:16 UTC, Steven Schveighoffer wrote: [...] It is not clear to me why the inout generated copy constructor of the B structure is not able to copy the A structure. [...] Why will copy constructor of ```struct B``` accept argument of type ```A```? You are right, I forgot the A member, now it is clear: struct A { int[] data; this(ref return scope A rhs){} this(ref return scope const A rhs) const {} this(ref return scope immutable A rhs) immutable {} } struct B { // default generated copy constructor, by section 14.15.6.2 this(ref return scope inout(B) src) inout { foreach (i, ref inout field; src.tupleof) this.tupleof[i] = field; } A a; } Error: none of the overloads of `__ctor` are callable using a `inout` object, candidates are: `A.this(return ref scope A rhs)` `A.this(return ref scope const(A) rhs)` `A.this(return ref scope immutable(A) rhs)` Thank you everybody.
Re: I do not understand copy constructors
On Thursday, 12 August 2021 at 14:57:16 UTC, Steven Schveighoffer wrote: On 8/12/21 10:08 AM, Learner wrote: On Thursday, 12 August 2021 at 13:56:17 UTC, Paul Backus wrote: On Thursday, 12 August 2021 at 12:10:49 UTC, Learner wrote: That worked fine, but the codebase is @safe: ```d cast from `int[]` to `inout(int[])` not allowed in safe code ``` So copy constructors force me to introduce trusted methods, while that was not necessary with postblits? A postblit would simply ignore the type qualifier--which can lead to undefined behavior. (Scroll down to the paragraph that begins "An unqualified postblit..." under ["Struct Postblits"][1] in the spec.) The copy constructor merely forces you to be honest about the safety of your code. In your case, I would recommend encapsulating the unsafe cast in a function like the following: ```d T[] dupWithQualifiers(T[] array) { auto copy = array.dup; return (() @trusted => cast(T[]) copy)(); } ``` You can then use this function in place of `dup` in your copy constructor. [1]: https://dlang.org/spec/struct.html#struct-postblit Thank you, now everything is more clear. A last question, if you do not mind, just to better understand inout. It seems a shortcut to avoid repeating the same function body for mutable, const, and immutable. Why the following code is not equal to the single inout constructor? struct A { int[] data; //this(ref return scope inout A rhs) inout { /*body*/ } this(ref return scope Timestamp rhs) { /*body*/ } this(ref return scope const Timestamp rhs) const { /*body*/ } this(ref return scope immutable Timestamp rhs) immutable { /*body*/ } } Error: Generating an `inout` copy constructor for `struct B` failed, therefore instances of it are uncopyable Inout is compatible only with inout, and not with the unrolled code it implies? inout is not like a template. It's a separate qualifier that generates only one function (not 3 unrolled ones). It's sort of viral like const is viral -- all underlying pieces have to support inout in order for you to write inout functions. -Steve It is not clear to me why the inout generated copy constructor of the B structure is not able to copy the A structure. struct A { int[] data; this(ref return scope A rhs){ /* body */ } this(ref return scope const A rhs) const { /* body */} this(ref return scope immutable A rhs) immutable { /* body */} } struct B { // default generated copy constructor, by section 14.15.6.2 this(ref return scope inout(B) src) inout { foreach (i, ref inout field; src.tupleof) this.tupleof[i] = field; } } Can point me to a code example of when the D generated copy constructor fails to copy A, and why?
Re: I do not understand copy constructors
On Thursday, 12 August 2021 at 13:56:17 UTC, Paul Backus wrote: On Thursday, 12 August 2021 at 12:10:49 UTC, Learner wrote: That worked fine, but the codebase is @safe: ```d cast from `int[]` to `inout(int[])` not allowed in safe code ``` So copy constructors force me to introduce trusted methods, while that was not necessary with postblits? A postblit would simply ignore the type qualifier--which can lead to undefined behavior. (Scroll down to the paragraph that begins "An unqualified postblit..." under ["Struct Postblits"][1] in the spec.) The copy constructor merely forces you to be honest about the safety of your code. In your case, I would recommend encapsulating the unsafe cast in a function like the following: ```d T[] dupWithQualifiers(T[] array) { auto copy = array.dup; return (() @trusted => cast(T[]) copy)(); } ``` You can then use this function in place of `dup` in your copy constructor. [1]: https://dlang.org/spec/struct.html#struct-postblit Thank you, now everything is more clear. A last question, if you do not mind, just to better understand inout. It seems a shortcut to avoid repeating the same function body for mutable, const, and immutable. Why the following code is not equal to the single inout constructor? struct A { int[] data; //this(ref return scope inout A rhs) inout { /*body*/ } this(ref return scope Timestamp rhs) { /*body*/ } this(ref return scope const Timestamp rhs) const { /*body*/ } this(ref return scope immutable Timestamp rhs) immutable { /*body*/ } } Error: Generating an `inout` copy constructor for `struct B` failed, therefore instances of it are uncopyable Inout is compatible only with inout, and not with the unrolled code it implies?
Re: I do not understand copy constructors
On Thursday, 12 August 2021 at 12:22:22 UTC, Tejas wrote: On Thursday, 12 August 2021 at 12:19:56 UTC, Tejas wrote: [...] Works with ```@safe``` as well Paul was just trying to make that other answer work, you don't have to make copy constructors ```@trusted``` Operations are needed on `other` data, that was the reason for a `postblit` in the original case: an `int[]` data array needs to be duplicated.
Re: I do not understand copy constructors
On Thursday, 12 August 2021 at 11:32:03 UTC, Paul Backus wrote: On Thursday, 12 August 2021 at 11:19:34 UTC, drug wrote: ```D struct A { int[] data; this(ref return scope inout A rhs) /* no inout here */ { data = rhs.data.dup; } } ``` The problem is that if you qualify the ctor itself then if you pass const/immutable rhs to it then the ctor is const/immutable too (like the args) and of course you cannot modify this, so the error. To make a copy ctor you need to qualify copy ctor args as inout but the copy ctor itself shall be mutable and have no const,immutable or inout qualifier. This is not true. Qualifying the ctor as `inout` works fine: https://run.dlang.io/is/Kpzp5M The problem in this example is that `.dup` always returns a mutable array, even if the array being copied is `inout`. The solution is to cast the copy back to the original type: ```d this(ref return scope inout A rhs) inout { data = cast(typeof(rhs.data)) rhs.data.dup; } ``` That worked fine, but the codebase is @safe: ```d cast from `int[]` to `inout(int[])` not allowed in safe code ``` So copy constructors force me to introduce trusted methods, while that was not necessary with postblits?
Re: I do not understand copy constructors
On Thursday, 12 August 2021 at 11:07:24 UTC, drug wrote: 12.08.2021 12:36, Learner пишет: > It seems that there is no easy way to transition from a postblit to a copy constructor, no? You just need both const and mutable copy ctors to replace inout one: ```D struct A { int[] data; this(ref return scope A rhs) { data = rhs.data.dup; } this(ref return scope const A rhs) const { data = rhs.data.dup; } } ``` the mutable copy ctor accepts mutable data and the const copy ctor accepts const and immutable data That still fails: Generating an `inout` copy constructor for `struct B` failed, therefore instances of it are uncopyable Also if I remove the `const` body (can I assign data if the method is const?) ```D struct A { int[] data; this(ref return scope A rhs) { data = rhs.data.dup; } this(ref return scope const A rhs) const {} } Generating an `inout` copy constructor for `struct B` failed, therefore instances of it are uncopyable ```
Re: I do not understand copy constructors
On Thursday, 12 August 2021 at 10:10:17 UTC, rikki cattermole wrote: On 12/08/2021 9:36 PM, Learner wrote: It seems that there is no easy way to transition from a postblit to a copy constructor, no? struct Foo { this(ref Foo other) { foreach(i, v; other.tupleof) this.tupleof[i] = v; } @disable this(this); } This results to: Generating an `inout` copy constructor for `struct A` failed, therefore instances of it are uncopyable
Re: I do not understand copy constructors
On Thursday, 12 August 2021 at 09:14:02 UTC, Paul Backus wrote: On Thursday, 12 August 2021 at 08:42:27 UTC, Learner wrote: struct A { int[] data this(ref return scope A rhs) { data = ths.data.dup; } } Generating an `inout` copy constructor for `struct B` failed, therefore instances of it are uncopyable What is an `inout` copy constructor? What should I change in A? When the compiler generates a copy constructor for a struct, it generates it with the following signature: ```d this(ref return scope inout(typeof(this)) src) inout ``` (Source: https://dlang.org/spec/struct.html#implicit-copy-constructors) Notice that both the `src` object and the object being constructed (`this`) are qualified with `inout`. `inout` is a special type qualifier that allows the same function to be used for mutable, `const`, and `immutable` arguments. To make this work, the compiler imposes heavy restrictions on what you can do with an `inout`-qualified object--only operations that are valid on mutable, `const`, *and* `immutable` objects are allowed for `inout`. (Source: https://dlang.org/spec/function.html#inout-functions) `A`'s copy constructor does not have any type qualifiers on its `rhs` argument or its `this` reference, so both default to mutable. In other words: `A`'s copy constructor can only be used to construct a mutable copy from a mutable original object. It *cannot* be used to construct an `inout` copy from an `inout` object. In order to make the generated copy constructor work, you need to give `A` a copy constructor that can copy `inout` objects. There are two possibilities here: 1. Make `A`'s copy constructor `inout`: `this(ref return scope inout A rhs) inout` 2. Make `A`'s copy constructor `const`: `this(ref return scope const A rhs) const` While option 2. is not working: struct A { int[] data; this(ref return scope const A rhs) const {} } Error: Generating an `inout` copy constructor for `struct A` failed, therefore instances of it are uncopyable Option .1 actually works, with an empty body, while it fails with the actual body: struct A { int[] data; this(ref return scope inout A rhs) inout { data = rhs.data.dup; } } Error: cannot implicitly convert expression `dup(cast(const(int)[])rhs.data)` of type `int[]` to `inout(int[])` It seems that there is no easy way to transition from a postblit to a copy constructor, no?
I do not understand copy constructors
I have a structure like, used by other structures: struct A { int[] data; this(this) { data = data.dup; } } I am trying to upgrade it to use copy constructor: struct A { int[] data this(ref return scope A rhs) { data = ths.data.dup; } } Generating an `inout` copy constructor for `struct B` failed, therefore instances of it are uncopyable What is an `inout` copy constructor? What should I change in A?
Re: variant visit not pure?
On Thursday, 7 May 2020 at 14:53:10 UTC, Steven Schveighoffer wrote: On 5/7/20 5:22 AM, learner wrote: [...] Because VariantN (the base of Algebraic) can literally hold anything, it cannot be pure, @safe, nothrow, @nogc. As others have recommended, I suggest using TaggedAlgebraic. I recently have been using it to create an algebraic type to hold a MYSQL value, so I can migrate the mysql-native library to be @safe (mysql-native currently uses Variant for everything). I added a special UDA to TaggedAlgebraic, so you can guarantee only @safe calls are allowed (for instance, if it can hold a pointer and an int, then opBinary!"+" can be marked as @safe if the operation fails when it's a pointer). TaggedAlgebraic could probably do the same for pure, but not sure about nothrow and @nogc, since it uses exceptions when things aren't valid. -Steve Modules of D standard library aren't in a good shape, if everyone suggests alternatives for a basic building block as variant. The types VariantN can hold are known at compile time, why can't it be specialized?
Re: variant visit not pure?
On Thursday, 7 May 2020 at 10:41:01 UTC, Simen Kjærås wrote: On Thursday, 7 May 2020 at 09:22:28 UTC, learner wrote: Good morning, Is there a reason why std.variant.visit is not inferring pure? ``` void test() pure { Algebraic!(int, string) alg; visit!( (string) => 0, (int) => 0)(alg); } Error: pure function test cannot call impure function test.visit!(VariantN!(16LU, int, string)).visit ``` std.variant.Algebraic is essentially a std.variant.Variant in different clothes. Variant is very flexible, and this comes at a cost (and isn't used in Algebraic, meaning you pay for things you don't use). Like Dukc said, you might be better off with Taggedalgebraic or SumType (https://code.dlang.org/packages/sumtype). Variant uses runtime type information to hold *any* type. Since Algebraic specifically only holds a few types, all the framework that's in place for Variant is wasted on Algebraic, and makes it less useful and less performant. -- Simen Thank you Simon and Dukc, I've find this: https://issues.dlang.org/show_bug.cgi?id=16662 So, it seems that Phobos isn't in a good shape ... what a pity!
variant visit not pure?
Good morning, Is there a reason why std.variant.visit is not inferring pure? ``` void test() pure { Algebraic!(int, string) alg; visit!( (string) => 0, (int) => 0)(alg); } Error: pure function test cannot call impure function test.visit!(VariantN!(16LU, int, string)).visit ``` Thank you
Re: Retrieve the return type of the current function
On Wednesday, 6 May 2020 at 08:04:16 UTC, Jacob Carlborg wrote: On 2020-05-05 19:11, learner wrote: On Tuesday, 5 May 2020 at 16:41:06 UTC, Adam D. Ruppe wrote: typeof(return) Thank you, that was indeed easy! Is it possible to retrieve also the caller return type? Something like: Yes, kind of: void foo(string caller = __FUNCTION__)() { import std.traits : ReturnType; alias R = ReturnType!(mixin(caller)); static assert(is(R == int)); } int bar() { foo(); return 0; } Awesome and beautiful, thank you!
Re: std.uni, std.ascii, std.encoding, std.utf ugh!
On Tuesday, 5 May 2020 at 19:24:41 UTC, WebFreak001 wrote: On Tuesday, 5 May 2020 at 18:41:50 UTC, learner wrote: Good morning, Trying to do this: ``` bool foo(string s) nothrow { return s.all!isDigit; } ``` I realised that the conversion from char to dchar could throw. I need to validate and operate over ascii strings and utf8 strings, possibly in separate functions, what's the best way to transition between: ``` immutable(ubyte)[] -> validate utf8 -> string -> nothrow usage -> isDigit etc immutable(ubyte)[] -> validate ascii -> AsciiString? -> nothrow usage -> isDigit etc string -> validate ascii -> AsciiString? -> nothrow usage -> isDigit etc ``` Thank you Thank you WebFreak, if you want nothrow operations on the sequence of characters (bytes) of the strings, use `str.representation` to get `immutable(ubyte)[]` and work on that. This is useful for example for doing indexOf (countUntil), startsWith, endsWith, etc. Make sure at least one of your inputs is validated though to avoid potentially handling or cutting off unfinished code points. I think this is the best way to go if you want to do simple things. What I really want is a way to validate an immutable(ubyte)[] sequence for UFT8 or ASCII, and from that point forward, apply functions like isDigit in nothrow functions. If your algorithm is sufficiently complex that you would like to still decode but not crash, you can also manually call .decode with UseReplacementDchar.yes to make it emit \uFFFD for invalid characters. I will simply reject invalid UTF8 input, that's coming from I/O To get the best of both worlds, use `.byUTF!dchar` which gives you an input range to iterate over and defaults to using replacement dchar. You can then call the various algorithm & array functions on it. Can you explain better? Unless you are working with different encodings than UTF-8 (like doing file or network operations) you shouldn't be needing std.encoding. I'm expecting UTF8 and ASCII encoding from I/O Thank you!
std.uni, std.ascii, std.encoding, std.utf ugh!
Good morning, Trying to do this: ``` bool foo(string s) nothrow { return s.all!isDigit; } ``` I realised that the conversion from char to dchar could throw. I need to validate and operate over ascii strings and utf8 strings, possibly in separate functions, what's the best way to transition between: ``` immutable(ubyte)[] -> validate utf8 -> string -> nothrow usage -> isDigit etc immutable(ubyte)[] -> validate ascii -> AsciiString? -> nothrow usage -> isDigit etc string -> validate ascii -> AsciiString? -> nothrow usage -> isDigit etc ``` Thank you
Re: Retrieve the return type of the current function
On Tuesday, 5 May 2020 at 16:41:06 UTC, Adam D. Ruppe wrote: typeof(return) Thank you, that was indeed easy! Is it possible to retrieve also the caller return type? Something like: ``` int foo() { return magic(); } auto magic(maybesomedefaulttemplateargs = ??)() { alias R = __traits(???); // --> int! } ``` Mixin templates maybe?
Retrieve the return type of the current function
Good morning, Is it possible something like this? ``` int foo() { __traits(some_trait, some_generic_this) theInt = 0; ``` I mean, without using the function name in the body, like ReturnType!foo ?
How define such scheleton classes
abstract class AbstractObject(S) if (IsSomeString!S) { } class OtherObject(S, bool R) : AbstractObject!S { int x; void Foo(int a, int b) { x = a + b; static if (R) // error { // more codes . } } } class OtherObjects(S) : AbstractObject!S { OtherObject!(S, bool) a, b; // error a = new OtherObject!(S, true)(); b = new OtherObject!(S, false)(); }
Re: get number of columns and rows in an ndarray.
On Wednesday, 15 June 2016 at 21:54:22 UTC, Seb wrote: On Wednesday, 15 June 2016 at 21:51:25 UTC, learner wrote: Hi, How can i get the number of cols and rows in and ndarray that has already been created? learner how about `shape`? http://dlang.org/phobos/std_experimental_ndslice_slice.html#.Slice.shape Thanks
get number of columns and rows in an ndarray.
Hi, How can i get the number of cols and rows in and ndarray that has already been created? learner
Re: How can convert the folowing to D.
On Friday, 1 April 2016 at 01:09:32 UTC, Ali Çehreli wrote: On 03/31/2016 05:34 PM, learner wrote: Hi, I have the following code in C++. rectangles.erase(rectangles.begin() + index); where rectangles is: std::vector rectangles; how can I do something similar in D. Learner. import std.stdio; void main() { int[] a = [ 1, 2, 3, 4, 5 ]; writefln("Before: %s", a); size_t index = 2; a = a[index .. $]; // <-- HERE writefln("After : %s", a); } Note that it's a cheap operation; the elements are still in memory and not destroyed. If you want to run their destructors you can call destroy() explicitly: import std.stdio; import std.algorithm; import std.range; struct Rect { int i; ~this() { writefln("Destroying %s", i); } } void main() { Rect[] a = iota(5).map!(i => Rect(i)).array; writefln("Before: %s", a); size_t index = 2; // If you need to run the destructors now: a[0 .. index].each!((ref e) => e.destroy); a = a[index .. $]; writefln("After : %s", a); } Prints Destroying 0 Destroying 1 Destroying 2 Destroying 3 Destroying 4 Before: [Rect(0), Rect(1), Rect(2), Rect(3), Rect(4)] Destroying 0 Destroying 1 After : [Rect(2), Rect(3), Rect(4)] Ali thanks
How can convert the folowing to D.
Hi, I have the following code in C++. rectangles.erase(rectangles.begin() + index); where rectangles is: std::vector rectangles; how can I do something similar in D. Learner.