std.typecons.Proxy + inheritance breaks cast'ing to inherited type
anonymous via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Tue Mar 17 16:58:22 PDT 2015
On Tuesday, 17 March 2015 at 07:56:19 UTC, Ali Çehreli wrote:
> > Why can't you do this instead?
> >
> > t opCast(t)()
> > if (is(typeof(cast(T)this)))
> > {
> > return cast(T)this;
> > }
>
> That has the same problem: 'cast(T)this' happens to be an
> explicit cast, which is disabled by the opCast overload for int.
>
> Ali
For classes, `T opCast(T)() {return cast(T) super;}` may be
viable.
For structs, it's seems more difficult to me.
`return this.to!T;` may try a cast(T), so it has the same problem
as `return cast(T) this;`: infinite recursion. Example:
----
struct StdConvTo
{
int* p;
int opCast(T : int)() {return 42;}
T opCast(T)() {import std.conv; return this.to!T;}
}
unittest
{
assert((cast(int) StdConvTo()) == 42); /* ok */
auto i = cast(immutable StdConvTo) StdConvTo(); /* infinite
recursion */
}
----
This applies to classes, too.
A reinterpret cast would allow casts that should be rejected:
----
struct Reinterpet
{
int* p;
int opCast(T : int)() {return 42;}
T opCast(T)() {return * cast(T*) &this;}
}
unittest
{
assert((cast(int) Reinterpet()) == 42); /* ok */
auto s = cast(float) Reinterpet(); /* compiles, but shouldn't
*/
}
----
Here's something that might work. Construct a "tuple" of the
struct's fields (i.e. same data but no opCast). Then cast that to
T.
----
struct TupleOf
{
int* p;
int opCast(T : int)() {return 42;}
T opCast(T)()
{
static struct Tuple(S) {S stuff;}
static Tuple!S tuple(S)(S stuff) {return Tuple!S(stuff);}
return cast(T) tuple(this.tupleof);
}
}
unittest
{
assert((cast(int) TupleOf()) == 42); /* ok */
auto i = cast(immutable TupleOf) TupleOf(); /* ok */
static assert(!__traits(compiles, cast(float) TupleOf())); /*
ok */
}
----
This is probably not perfect either.
More information about the Digitalmars-d-learn
mailing list