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