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:
```d
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:
```d
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.
```