Re: C++'s this() equivalent?
On Friday, 16 June 2023 at 01:54:22 UTC, Jonathan M Davis wrote: ```d doSomething(); scope(exit) undoSomething(); ``` Thank you for your `wonderful summary`. It's worth saving the link.
Re: C++'s this() equivalent?
On Friday, 16 June 2023 at 01:45:35 UTC, CM wrote: ```d auto m = Man(); assert(m.name == defaultName); ``` Do note that one cannot simultaneously have a constructor and a static opCall, even if their parameters differ. Thank you for your reply. This should be enough, as this type of RAII is basically a `temporary struct`.
Re: C++'s this() equivalent?
On Thursday, June 15, 2023 7:54:22 PM MDT Jonathan M Davis via Digitalmars-d- learn wrote: > On Thursday, June 15, 2023 7:18:25 PM MDT zjh via Digitalmars-d-learn wrote: > > On Friday, 16 June 2023 at 01:00:05 UTC, Steven Schveighoffer > > > > wrote: > > > B b = B.make(); // call factory function > > > > > > -Steve > > > > Thank you for your tip. > > If could simplify it a bit more, it would be even better. It's > > really uncomfortable without `this()`. > > The reasons for it have to do with how D in general is set up to require > that the value of all types be known at compile-time. This should say that it's set up to require that the _default_ value of all types be known at compile-time. - Jonathan M Davis
Re: C++'s this() equivalent?
On Thursday, June 15, 2023 7:18:25 PM MDT zjh via Digitalmars-d-learn wrote: > On Friday, 16 June 2023 at 01:00:05 UTC, Steven Schveighoffer > > wrote: > > B b = B.make(); // call factory function > > > > -Steve > > Thank you for your tip. > If could simplify it a bit more, it would be even better. It's > really uncomfortable without `this()`. The reasons for it have to do with how D in general is set up to require that the value of all types be known at compile-time. Types in general use default initialization rather than default construction. The language then depends on this for a variety of things. For instance, when you construct a an array (dynamic or static), it fills in all of the values in the array by bit-blitting the init value of the element type onto the elements. Similarly, when you expand the length of a dynamic array, it bit-blits the init value of the element type onto the new elements. Other language features such as in and out on function parameters rely on the init value as well. For all of that to work, the type's init value must be known at compile-time, which means that default construction is off the table. For most things, this is just fine and is quite beneficial. However, it does make certain things (like RAII) more annoying than they are in C++. That being said, as has been pointed out, the simple workaround if you want RAII is to use a factory function. It's a bit of extra typing, since you have to call a function instead of simply declaring the variable, but the factory function then works like the constructor would have in C++, and the destructor does the clean-up like it would have in C++. It just comes with the downsides of the extra typing and the fact that it's possible to have variables of that type that did not go through the factory function, because they were default-initialized with the init value rather than constructed via the factory function. To work around that, you can @disable this so that the type doesn't have an init value, but then it can't be used in any context where the init value would be required, which can become very annoying. Unlike structs, classes can have default constructors, but that's because they sit on the heap, and technically, when you refer to a class type, you're almost always referring to a class reference rather than to the object itself. And the class reference has an init value of null, so it can be used in all of the places where an init value is required, whereas a class object is never actually used in such a situation. For RAII, as an alternative to using a factory function on a struct, you can use a class and then use https://dlang.org/phobos/std_typecons.html#scoped to ensure that it gets destroyed when it leaves scope. There are also scope statements for ensuring that something is run when you exit the scope, but it isn't really RAII, since you'd still have to call the initialization portion of things separately. E.G. doSomething(); scope(exit) undoSomething(); It just makes it easier to ensure that what you want to run when the scope is exited is always run. So, there are several ways that you could go about trying to get behavior similar to RAII in C++ even if you can't actually have RAII. Probably the best method though is to just use a factory function on a struct. Yes, it's more annoying than proper RAII, but it's a side effect of other benefits that D gives that C++ does not. - Jonathan M Davis
Re: C++'s this() equivalent?
On Friday, 16 June 2023 at 01:18:25 UTC, zjh wrote: On Friday, 16 June 2023 at 01:00:05 UTC, Steven Schveighoffer wrote: B b = B.make(); // call factory function -Steve Thank you for your tip. If could simplify it a bit more, it would be even better. It's really uncomfortable without `this()`. One could define a static opCall in his aggregate. It's still a factory function, but one might prefer the syntax a bit more. ```d immutable defaultName = "John"; struct Man { static auto opCall() { typeof(this) this_; this_.name = defaultName; return this_; } string name; } auto m = Man(); assert(m.name == defaultName); ``` Do note that one cannot simultaneously have a constructor and a static opCall, even if their parameters differ.
Re: C++'s this() equivalent?
On Friday, 16 June 2023 at 01:00:05 UTC, Steven Schveighoffer wrote: B b = B.make(); // call factory function -Steve Thank you for your tip. If could simplify it a bit more, it would be even better. It's really uncomfortable without `this()`.
Re: C++'s this() equivalent?
On 6/15/23 8:52 PM, zjh wrote: On Friday, 16 June 2023 at 00:35:48 UTC, Steven Schveighoffer wrote: Instead, you can use factory functions to initialize. How can `factory functions` be used to achieve effects similar to `'RAII'`? Thank you. B b; becomes B b = B.make(); // call factory function All my uses of RAII depend on copy construction and destruction. Construction is easy enough because I have to explicitly declare it anyway. -Steve
Re: C++'s this() equivalent?
On Friday, 16 June 2023 at 00:35:48 UTC, Steven Schveighoffer wrote: Instead, you can use factory functions to initialize. -Steve How can `factory functions` be used to achieve effects similar to `'RAII'`? Thank you.
Re: C++'s this() equivalent?
On 6/15/23 8:45 PM, zjh wrote: On Friday, 16 June 2023 at 00:35:48 UTC, Steven Schveighoffer wrote: But there is no way in D to have e.g.: ```d B b; // runs a constructor ``` As a `C++` user, it is very terrible to simplify `RAII` without such a method. Why must `this()` be disabled? Can't there be a constructor? In a constructor, you can complete `some work`. Without it, how can you simplify `RAII`?. D was not originally designed with RAII. That was added later (D1 structs did not have ctors or dtors). The benefit of *not* having parameterless constructors is that default construction is always defined *and* available at compile time. What is wrong with using a parameter constructor or factory function? What is the feature you are trying to build that you can with C++, but not with D? I'm not saying I agree with the limitation, just want to know more. -Steve
Re: C++'s this() equivalent?
On Friday, 16 June 2023 at 00:35:48 UTC, Steven Schveighoffer wrote: But there is no way in D to have e.g.: ```d B b; // runs a constructor ``` -Steve As a `C++` user, it is very terrible to simplify `RAII` without such a method. Why must `this()` be disabled? Can't there be a constructor? In a constructor, you can complete `some work`. Without it, how can you simplify `RAII`?.
Re: C++'s this() equivalent?
On Thursday, 15 June 2023 at 21:48:10 UTC, Ali Çehreli wrote: I have difficulty understanding the question. I think the nested structs, extern(C), static members, etc. confuse me. I am assuming they are not related to this question. Ali I used the `class` to call the` constructor/destructor (destroy)`, but after they leave the scope, they do not call the`destructor (destroy)`. `Nested class` is because I want to directly use members of `external struct`, but in reality, I cannot access them directly. Therefore, I only have to use ` static members`,. `extern(C)` is to use `BetterC`,. The purpose is mainly to complete `RAII`, completing one part of the work after entering the scope and another part of the work after leaving the scope.
Re: C++'s this() equivalent?
On 6/15/23 8:31 PM, zjh wrote: Because disabled `this()`, the behavior of `this(int i)`is inconsistent and cannot achieve similar `RAII` as `C++`. What should I do? You cannot have parameter-less constructors in D structs. However, destruction works the same. Instead, you can use factory functions to initialize. But there is no way in D to have e.g.: ```d B b; // runs a constructor ``` -Steve
Re: C++'s this() equivalent?
On Thursday, 15 June 2023 at 21:48:10 UTC, Ali Çehreli wrote: And this is by design: In D, we rename the type and be done with it. In C++, one needs to rename a number of functions as well. Ali ```d static int e=40; struct B{ int m; this(int i){ printf("%i",e);m=i; } ~this(){ e=m; printf("%i",e); } //After leaving the scope, restore the original value } // definition, // usage void f(){ B b=e;e=6; }//e Restore to 40. ``` But I want like follow, but due to the `disable this()`,I can't: ```d void f(){ B b;e=6; } ``` Because disabled `this()`, the behavior of `this(int i)`is inconsistent and cannot achieve similar `RAII` as `C++`. What should I do?
Re: C++'s this() equivalent?
On 6/15/23 08:15, zjh wrote: > I want `B` to become the following version similar to 'C++'. What should > I do? I have difficulty understanding the question. I think the nested structs, extern(C), static members, etc. confuse me. I am assuming they are not related to this question. > ```cpp > struct B{ > int m; > B(){ Do you want to be able to use the name of the user-defined type to mean "constructor", "destructor", etc? If so, no, it's not possible without preprocessing the text potentially with a C preprocessor. And this is by design: In D, we rename the type and be done with it. In C++, one needs to rename a number of functions as well. Ali
C++'s this() equivalent?
```d import core.stdc.stdio; struct A{ static int e=40; struct B{ int m; this(int i){ printf("%i",e);m=i; } ~this(){ e=m; printf("%i",e); } } void f(){ B b=e;e=6; } void g(){ printf("%i",e); } } extern(C)void main(){ A a; a.f(); a.g(); } ``` I want `B` to become the following version similar to 'C++'. What should I do? ```cpp struct B{ int m; B(){ printf("%i",e);m=e; } ~B(){ e=m; printf("%i",e); } } ``` Thank you.
Re: C#'s 'is' equivalent in D
On Thursday, 10 October 2019 at 16:33:47 UTC, H. S. Teoh wrote: On Thu, Oct 10, 2019 at 03:58:02PM +, jmh530 via Digitalmars-d-learn wrote: On Thursday, 10 October 2019 at 15:47:58 UTC, Just Dave wrote: > In C# you can do something like: > > > if (obj is Person) > { > var person = obj as Person; > // do stuff with person... > } [...] You mean something like below: class Person { int id; this(int x) { id = x; } } void main() { auto joe = new Person(1); if (is(typeof(joe) == Person)) { assert(joe.id == 1); } } Unfortunately, typeof is a compile-time construct, so this will not work if you're receiving a Person object via a base class reference. The correct solution is to cast the base class to the derived type, which will yield null if it's not an instance of the derived type. T Ah, you mean something like below: class Person { int id; this(int x) { id = x; } } class Employee : Person { int job_id; this(int x, int y) { super(x); job_id = y; } } void main() { import std.stdio : writeln; Person joe = new Employee(1, 2); if (is(typeof(joe) == Employee)) { writeln("here"); //not called in this case } }
Re: C#'s 'is' equivalent in D
On Thu, Oct 10, 2019 at 03:58:02PM +, jmh530 via Digitalmars-d-learn wrote: > On Thursday, 10 October 2019 at 15:47:58 UTC, Just Dave wrote: > > In C# you can do something like: > > > > > > if (obj is Person) > > { > > var person = obj as Person; > > // do stuff with person... > > } [...] > You mean something like below: > > class Person { > int id; > this(int x) { > id = x; > } > } > > void main() { > auto joe = new Person(1); > if (is(typeof(joe) == Person)) { > assert(joe.id == 1); > } > } Unfortunately, typeof is a compile-time construct, so this will not work if you're receiving a Person object via a base class reference. The correct solution is to cast the base class to the derived type, which will yield null if it's not an instance of the derived type. T -- LINUX = Lousy Interface for Nefarious Unix Xenophobes.
Re: C#'s 'is' equivalent in D
On Thursday, 10 October 2019 at 15:47:58 UTC, Just Dave wrote: In C# you can do something like: if (obj is Person) { var person = obj as Person; // do stuff with person... } where you can check the type of an object prior to casting. Does D have a similar mechanism? It's so widely useful in the C# realm that they even added syntactic sugar to allow: if (obj is Person person) { // do stuff with person... } I would presume since D has reference objects there must exist some mechanism for this... You mean something like below: class Person { int id; this(int x) { id = x; } } void main() { auto joe = new Person(1); if (is(typeof(joe) == Person)) { assert(joe.id == 1); } }
Re: C#'s 'is' equivalent in D
On Thursday, 10 October 2019 at 15:53:20 UTC, Adam D. Ruppe wrote: On Thursday, 10 October 2019 at 15:47:58 UTC, Just Dave wrote: if (obj is Person person) Looks the same as D's if(auto person = cast(Person) obj) { // use person in here } else { // it was some other type } Excellent!
Re: C#'s 'is' equivalent in D
On Thursday, October 10, 2019 9:47:58 AM MDT Just Dave via Digitalmars-d- learn wrote: > In C# you can do something like: > > > if (obj is Person) > { > var person = obj as Person; > // do stuff with person... > } > > where you can check the type of an object prior to casting. Does > D have a similar mechanism? It's so widely useful in the C# realm > that they even added syntactic sugar to allow: > > if (obj is Person person) > { > // do stuff with person... > } > > I would presume since D has reference objects there must exist > some mechanism for this... D's solution is basically the same as C++'s solution. You cast and then check whether the result is null. So, if(cast(Person)obj !is null) { } or since using a pointer or reference in an if condition checks whether it's null or not if(cast(Person)obj) { } and you can even declare a variable that way if you want. e.g. if(auto person = cast(Person)obj) { } When D's is is used to compare two objects, it checks whether they're equal bitwise. So, it's typically used for comparing pointers or references for equality (whereas using == with references would compare the objects themselves for equality). - Jonathan M Davis
Re: C#'s 'is' equivalent in D
On 10/10/19 6:47 PM, Just Dave wrote: In C# you can do something like: if (obj is Person) { var person = obj as Person; // do stuff with person... } where you can check the type of an object prior to casting. Does D have a similar mechanism? It's so widely useful in the C# realm that they even added syntactic sugar to allow: if (obj is Person person) { // do stuff with person... } I would presume since D has reference objects there must exist some mechanism for this... ```D if (auto person = cast(Person) obj) { // do stuff with person... } ```
Re: C#'s 'is' equivalent in D
On Thursday, 10 October 2019 at 15:47:58 UTC, Just Dave wrote: if (obj is Person person) Looks the same as D's if(auto person = cast(Person) obj) { // use person in here } else { // it was some other type }
Re: C#'s 'is' equivalent in D
Even though static solutions would be more performance minded, I'd actually prefer to see the runtime equivalent so I don't have to rethink how I think as performance isn't really my major concern right now.
C#'s 'is' equivalent in D
In C# you can do something like: if (obj is Person) { var person = obj as Person; // do stuff with person... } where you can check the type of an object prior to casting. Does D have a similar mechanism? It's so widely useful in the C# realm that they even added syntactic sugar to allow: if (obj is Person person) { // do stuff with person... } I would presume since D has reference objects there must exist some mechanism for this...