Implicit type conversion
Jonathan M Davis
jmdavisProg at gmx.com
Sun Jan 9 21:29:32 PST 2011
On Saturday 08 January 2011 13:16:54 Michal Minich wrote:
> Use case:
>
> import std.variant;
>
> void foo (Variant v) {}
>
> void main () {
> Variant v = 3; // ok, this (....) called
> v = 3; // ok, opAssing called
> foo (v); // ok, struct copy, this(this) called
> foo (3); // error
> }
>
> I'm trying to understand what is needed to make this work from language
> design perspective. Is there already known/proposed solution to make this
> work? What comes to my mind as first - Variant constructor should be
> called on last line, the same way as on the first. But maybe to solve
> this, another operator is needed, opImplicitConvertFrom ...
There are definitely folks who want opImplicitCast (I think that it's pretty much
going to be necessary to get std.typecons.Rebindable to work entirely
correctly), and there's at least a decent chance that it will get added, but in
general, D avoids implicit casting in order to avoid issues where you call
functions which you don't really want to call (see http://is.gd/ksVli ).
Regardless, opImplicitCast wouldn't help you here anyway, because you need to
cast from an int to a Variant rather than the other way around, and it's not
like int is going to have opImplicitCast defined, even if it did exist.
Generally, you just need to give the correct type, which in this case would
presumably mean foo(Variant(3)). It might be a bid annoying, but it avoids
problems where you end up calling a function overload that you didn't intend to.
If you really don't want to do that, then I believe that you're going to have to
create another function overload for Foo which takes an int and deals with the
conversion to Variant for you.
> Second question. Why is needed to have both - strut constructor (this)
> and opAssing. In variant case, constructor just forwards to opAssing.
> From high level point of view, I don't see any reason both should behave
> differently...
There could be a difference of efficiency depending on the type. It could be more
efficient to do something differently in one. For instance, that's why we have both
opAssign and opOpAssign. Technically, you could just not have opOpAssign and use
the combination of opAssign and opBinary to do it, but then you're likely to end
up with extra heap allocations and the like. It could be the same with a
constructor and opAssign, depending on the type.
For the most part, D has tried to reduce how many operators you have to declare
when they're related (such us using opCmp() to give you <, <=, >=, and >), but
it does create extra ones in cases where there's a good chance that it's more
efficient to have separate definitions (such as using opEquals() for == and !=
rather than using opCmp() for that).
- Jonathan M Davis
More information about the Digitalmars-d-learn
mailing list