www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Small suggestion for default constructors

reply TheZipCreator <thezipcreator protonmail.com> writes:
Something I find quite annoying to do is to create a constructor 
that only sets the given properties. For example:

```d
class Foo {
	int x;
	int y;
	int z;
	this(int x, int y, int z) {
		this.x = x;
		this.y = y;
		this.z = z;
	}
}
```
For structs, it automatically generates a constructor, and it'd 
be nice if you could autogenerate constructors for classes too, 
kinda like this:
```d
class Foo {
	int x;
	int y;
	int z;
	default this(int x, int y, int z);
}
```
which would just be syntactic sugar for the former.

this could also be used for structs too if you've already 
specified a constructor:
```d
struct Vector3 {
	float x;
	float y;
	float z;
	this(Vector2 v) {
		x = v.x;
		y = v.y;
	}
	default this(float x, float y, float z);
}
```
I feel like this would avoid a lot of boilerplate and make things 
more concise.
Jan 16 2023
next sibling parent reply Mike Parker <aldacron gmail.com> writes:
On Tuesday, 17 January 2023 at 02:45:30 UTC, TheZipCreator wrote:

 For structs, it automatically generates a constructor, and it'd
There's a distinction. The default initializer for a struct is the `.init` value of each member. `T()` is not a default constructor, but a struct literal that's equivalent to `T.init`. The default initializer for classes is always null and we don't have class literals. I'm not arguing against your suggestion here. Just wanted to point out the distinction.
Jan 16 2023
parent Paul Backus <snarwin gmail.com> writes:
On Tuesday, 17 January 2023 at 03:02:46 UTC, Mike Parker wrote:
 On Tuesday, 17 January 2023 at 02:45:30 UTC, TheZipCreator 
 wrote:

 For structs, it automatically generates a constructor, and it'd
There's a distinction. The default initializer for a struct is the `.init` value of each member. `T()` is not a default constructor, but a struct literal that's equivalent to `T.init`.
Almost. There is one situation where `T.init` and `T()` are different, and that's when `T` is a nested struct. ```d void main() { int n; struct S { int fun() { return ++n; } } auto s1 = S(); assert(s1.fun() == 1); // ok auto s2 = S.init; assert(s2.fun() == 2); // segmentation fault } ``` In the above code, using `S()` initializes `s1`'s context pointer at runtime to point to `main`'s stack frame, allowing `s1.fun` to access the variable `n`. Using `S.init` to initialize `s2`, however, sets the context pointer to `null`, so when `s2.fun` is called, the program crashes.
Jan 19 2023
prev sibling next sibling parent reply Adam D Ruppe <destructionator gmail.com> writes:
On Tuesday, 17 January 2023 at 02:45:30 UTC, TheZipCreator wrote:
 	default this(float x, float y, float z);
Try this out: class Foo { int x; int y; int z; // one little function this(typeof(this.tupleof) t) { this.tupleof = t; } } void main() { auto foo = new Foo(1, 2, 3); assert(foo.x == 1); assert(foo.y == 2); assert(foo.z == 3); }
Jan 16 2023
next sibling parent TheZipCreator <thezipcreator protonmail.com> writes:
On Tuesday, 17 January 2023 at 03:12:09 UTC, Adam D Ruppe wrote:
 On Tuesday, 17 January 2023 at 02:45:30 UTC, TheZipCreator 
 wrote:
 	default this(float x, float y, float z);
Try this out: class Foo { int x; int y; int z; // one little function this(typeof(this.tupleof) t) { this.tupleof = t; } } void main() { auto foo = new Foo(1, 2, 3); assert(foo.x == 1); assert(foo.y == 2); assert(foo.z == 3); }
ooh, that's an interesting usage of `tupleof`. I didn't even know it could be used as an lvalue. This is a bit unclear if you don't know the internals of D though. also, this wouldn't work if you just want to initialize one or two values and not all of them, but still could be useful.
Jan 17 2023
prev sibling next sibling parent "H. S. Teoh" <hsteoh qfbox.info> writes:
On Tue, Jan 17, 2023 at 03:12:09AM +0000, Adam D Ruppe via Digitalmars-d wrote:
[...]
 class Foo {
         int x;
         int y;
         int z;
 
         // one little function
         this(typeof(this.tupleof) t) {
                 this.tupleof = t;
         }
 }
[...] Very nice! Gotta use this in my own code sometime. :-D T -- Life is too short to run proprietary software. -- Bdale Garbee
Jan 17 2023
prev sibling parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 1/16/23 19:12, Adam D Ruppe wrote:
          // one little function
          this(typeof(this.tupleof) t) {
                  this.tupleof = t;
          }
Which can be mixed-in and can have default arguments: mixin template memberAssigningConstructor() { // one little function this(typeof(this.tupleof) t = typeof(this.tupleof).init) { this.tupleof = t; } } import std.stdio; class Foo { int x; int y; int z; mixin memberAssigningConstructor!(); override string toString() const { import std.format : format; return format!"%s %s %s"(x, y, z); } } void testWith(Args...)(Args args) { auto f = new Foo(args); writeln(f); } void main() { testWith(); testWith(1); testWith(1, 2); testWith(1, 2, 3); } Outputs: 0 0 0 1 0 0 1 2 0 1 2 3 However, I recommend testing compilation speeds because I used mixed-in tupleof for opCmp implementations in a project about 3 years ago. There were only 6 instances of that usage but the compilation times were noticeably affected. (Disclaimer: There were 6 instances but I think those modules were imported very many times by other modules.) Replacing the tupleof idiom with trivial functions fixed the compilation speed issue for me. Ali
Jan 17 2023
prev sibling next sibling parent JN <666total wp.pl> writes:
On Tuesday, 17 January 2023 at 02:45:30 UTC, TheZipCreator wrote:
 I feel like this would avoid a lot of boilerplate and make 
 things more concise.
Yeah, it's something I miss greatly from D (named constructors are another feature I miss). In Dart you can do it like this: class Point { num x; num y; Point(this.x, this.y); } var p = Point(10.0, 20.0);
Jan 17 2023
prev sibling parent Salih Dincer <salihdb hotmail.com> writes:
On Tuesday, 17 January 2023 at 02:45:30 UTC, TheZipCreator wrote:
 For structs, it automatically generates a constructor, and it'd 
 be nice if you could autogenerate constructors for classes too, 
 kinda like this:
You might like monkyyy's withMe() mixin template... **Source Link:** https://forum.dlang.org/post/ipgwqcnfxltoijavflro forum.dlang.org **Sample Print:** `S!(Letter)(ab, [10, 20], true)` ```d auto withMe(string elements, Me, T...)(Me me, T arg){ with(me) mixin(elements); return me; } enum { A = 97, B, C, D } enum a = Letter(A); enum b = Letter(B); struct Letter { char letter = 96; alias letter this; } import std.stdio; void main() { struct S(T) { T[] word; int[] nums; bool view; } auto test = S!Letter().withMe!q{ word = [a, b]; nums = [10, 20]; view = true; }; test.writeln; } ``` SDB 79
Jan 17 2023