On Tuesday, 1 March 2022 at 08:16:13 UTC, Mike Parker wrote:
> On Tuesday, 1 March 2022 at 07:16:11 UTC, bauss wrote:
> Right now if you want to add an additional cast then you have to implement ALL the default behaviors and then add your custom cast.
It's two template functions like the OP used: one for T to catch everything, and one specialization.
> That doesn't seem correct to me at least.
Depends on your perspective I guess. For the inverse, when you want to allow only one kind of cast and prevent everything else, you only have to implement one template right now. If that were not the case, then you'd have to implement an additional catch-all template that bombs out with a static assert.
So either way makes sense, IMO. Though I totally understand how the current behavior can be a surprise when people expect it to behave like, e.g., C++.
But D is not C++. So is opCast
intended to expand the list of target types (like C++), or is it intended to define it? The spec says, "To define how one type can be cast to another", which doesn't really answer the question.
Now is possible this:
import std.stdio;
struct Foo{
int i;
this(int i)@safe{
this.i = i;
writeln("ctor(", i, "): ", cast(void*)&this);
}
Foo opCast(T, this This)()@safe
if(is(immutable T == immutable This)){
return Foo(2);
}
~this()@safe{
writeln("dtor(", i, "): ", cast(void*)&this);
}
}
struct Bar{
const Foo foo;
this(int i)@safe{
this.foo = Foo(i);
}
}
void main()@safe{
Bar bar = Bar(1);
}
Result:
ctor(1): 7FFE0D5A94A8 //dtor for Foo(1) is never called.
ctor(2): 7FFE0D5A9410
dtor(2): 7FFE0D5A9470
dtor(2): 7FFE0D5A9470 //dtor for Foo(2) is called twice.