If I try to append a Nullable struct to an array, I have to cast it, but not when I assign it to the array using an index. Is this a bug or is it supposed to work this way?
import std.typecons;
struct Foo {
string s;
int i;
}
void main() {
f1();
f2();
f3();
}
void f1() {
auto foos = new Nullable!Foo[](10);
foos[0] = Foo("abc", 10); // OK
}
void f2() {
Nullable!Foo[] foos;
foos ~= Foo("abc", 10); // Error: cannot append type Foo to type Nullable!(Foo)[]
}
void f3() {
Nullable!Foo[] foos;
foos ~= cast(Nullable!Foo)Foo("abc", 10); // OK
}
That's intentional, though I'd say not ideal. D lacks implicit construction (except in one really obscure case, variadic class functions if you're curious) and what you're asking for there is implicit construction of the Nullable - given the Foo, you want to build a Nullable wrapper around it, and D doesn't let you do that without some kind of explicit action, either a director constructor call or a function call that acts like one* (in some user-defined arrays, an overloaded concat operator will do the construction for you, but you are using a built-in array so it is not overloaded at all).
If you assign it, it calls Nullable!T.opAssign
on the already-constructed item; an overloaded function implemented in the type http://dpldocs.info/experimental-docs/std.typecons.Nullable.opAssign.html which replaces the contents.
But concatenation means a new element needs to be made, which hits this construction rule.
I say it is not ideal because I so wish D had this feature. C++ had bad experiences with implicit constructors, but that's because ALL C++ constructors were implicit by default, unless you used the explicit
keyword explicitly. D avoided that mistake, but threw the baby out with the bathwater :(
Casting a value v to a struct S, when value is not a struct of the same type, is equivalent to:
S(v)