On Thu, 09 Jun 2011 14:24:55 -0400, Jonathan M Davis <[email protected]>
wrote:
On 2011-06-09 10:58, Steven Schveighoffer wrote:
On Thu, 09 Jun 2011 13:33:28 -0400, Jonathan M Davis
<[email protected]>
wrote:
>> On 09.06.2011 16:33, Steven Schveighoffer wrote:
>> > Hm... this involves cast(Duration)x? That seems like a dangerous
thing
>> > for a common operation, no?
>
> There's nothing dangerous about it. It's an overloaded opCast, not a
> built-in
> cast. Now, there was some talk of figuring out how to set it up so
that
> you
> could define in your type how to use the to function to convert
instead,
> and
> that would be better (though I have no idea what the situation with
that
> is or
> what's involved in that), but an overloaded opCast is the same as a
> normal
> function except for its calling syntax, so it's perfectly safe.
What I mean is, whenever you use the blunt instrument 'cast' anything
can
happen. This code:
cast(x)y;
can do a lot of damage, depending on what x and y are. IIRC, you
recently
said that one should avoid use casting if you can help it :)
It doesn't matter if the underlying cast is safe, the keyword cast means
"do whatever I say". It doesn't mean "do whatever I say but only if it's
an opCast operation". One slight misstep, and the compiler will silently
obey instead of giving you an error. We've been told numerous times "if
you want to find all the places where your code bypasses the type
system,
search for the word cast".
My point is, why can't this function simply be a function (like
toDuration()). You can also define opCast to do the same thing, but I
think the ability to avoid typing that dreaded keyword should be
available.
I think that it makes good sense to include the opCasts for when they're
necessary, but I do agree that it would be ideal not to need them. I'd
much
prefer to be using to!() than opCast, but I don't know what the proper
way to
do that is (include overloads for it in core.time and std.datetime?). I
didn't
include functions like toDuration because it seemed silly to create non-
standard, specific functions for that what opCast is intended for. And I
don't
object to opCast casts in the same way that I object to the built in
ones,
since it's really just a function call. But I would prefer that to!() be
used,
since that's appropriately standard and generally safe. I just don't
know what
the proper way to do that is. It seems overkill to add overloads for
every
type in Phobos to std.conv, and that doesn't work for types outside of
Phobos
anyway.
The problem with cast (and we've gone over this before ad nauseum) is that
you can't specify to the compiler what type of cast you are expecting to
run. I could think I'm going to invoke opCast, but instead do away with
some sort of const, or reinterpret the bits as something else.
But I agree, there should be a standard way to hook std.conv.to. I like
Andrej's idea of having std.conv.to use a member function named to (or
opTo?) if possible.
That means, all you need to define in your struct/class is:
T to(T)() if (is(T == Duration)) {...}
then std.conv.to just does x.to!Duration() if it compiles.
It's sort of like std.range.put, which calls put if it exists as a member
function of an output range, or tries other things if that doesn't work.
-Steve