#271 Overload cast outside type header

open
nobody
None
2013-05-10
2013-05-06
John Wright
No

Quoted from here: http://www.freebasic.net/forum/viewtopic.php?f=3&t=21152

I'm wondering if it's likely in the future to allow cast overloading from outside type declarations, to match the current syntax for overloading arithmetic operators. As of now these are allowed:

type foo
declare operator cast as bar
end type

declare operator + (f as foo, b as bar) as foo

But not these:

type foo
declare operator + (as bar) as foo
end type

declare operator cast (f as foo, b as bar) as foo

As "declare operator + (as bar) as foo" is planned to be allowed inside type declarations (so says the compiler error), it would make sense to allow cast overloading outside type dec's.

This is already possible by using "function" instead of "operator", but I feel this would allow for more consistency.

Wishful code (forgive the example):

type velocity
as double speed, direction
end type

type vector2d
as double x, y
end type

operator cast (vel as velocity) as vector2d
return type<vector2d>(cos(vel.direction)speed, -sin(vel.direction)speed)
end operator

operator cast (vec as vector2d) as velocity
return type<velocity>(sqr(vec.x^2 + vec.y^2), acos(x / magnitude))
end operator

dim as vector2d veca = type<vector2d>(-5, 6)
dim as velocity vela = cast(velocity, veca)
dim as velocity velb = type<velocity>(2, 3.14)
dim as vector2d vecb = cast(vector2d, velb)

print "("; veca.x; ","; veca.y; ") => speed ="; vela.speed; ", direction ="; vela.direction
print "("; vecb.x; ","; vecb.y; ") => speed ="; velb.speed; ", direction ="; velb.direction

Current code:

type __vector2d as vector2d

type velocity
declare operator cast as __vector2d ptr
as double speed, direction
end type

type vector2d
declare operator cast as velocity
as double x, y
end type

operator velocity.cast as vector2d ptr
return new vector2d (type<vector2d>(cos(direction)speed, -sin(direction)speed))
end operator

operator vector2d.cast as velocity
dim as double magnitude = sqr(x^2 + y^2)
return type<velocity>(magnitude, acos(x / magnitude))
end operator

dim as vector2d veca = type<vector2d>(-5, 6)
dim as velocity vela = cast(velocity, veca)
dim as velocity velb = type<velocity>(2, 3.14)
dim as vector2d ptr vecb = cast(vector2d ptr, velb)

print "("; veca.x; ","; veca.y; ") => speed ="; vela.speed; ", direction ="; vela.direction
print "("; vecb->x; ","; vecb->y; ") => speed ="; velb.speed; ", direction ="; velb.direction
delete vecb

This way "type __foo as foo" need not be used, thus avoiding the implications of using pointers.

Discussion

  • John Wright
    John Wright
    2013-05-10

    fxm has pointed out a silly mistake of mine.

    About the non-member operator 'cast' declaration, I think that:
    'declare operator cast (f as foo, b as bar) as foo'
    must be corrected as:
    'declare operator cast (b as bar) as foo'

     
  • Another solution for this example is to always use a member operator 'cast' with a return type that has been forward declared, but in addition this return type is declared return by reference (with a fbc version that supports the new branch 'return-byref'):

    type __vector2d as vector2d
    
    type velocity
        declare operator cast byref as __vector2d
        as double speed, direction
    end type
    
    type vector2d
        declare operator cast as velocity
        as double x, y
    end type
    
    operator velocity.cast byref as vector2d
        static as vector2d vec
        vec = type<vector2d>(cos(direction)*speed, -sin(direction)*speed)
        return vec
    end operator
    
    operator vector2d.cast as velocity
        dim as double magnitude = sqr(x^2 + y^2)
        return type<velocity>(magnitude, acos(x / magnitude))
    end operator
    
    dim as vector2d veca = type<vector2d>(-5, 6)
    dim as velocity vela = cast(velocity, veca)
    dim as velocity velb = type<velocity>(2, 3.14)
    dim as vector2d vecb = cast(vector2d, velb)
    
    print "("; veca.x; ","; veca.y; ") => speed ="; vela.speed; ", direction ="; vela.direction
    print "("; vecb.x; ","; vecb.y; ") => speed ="; velb.speed; ", direction ="; velb.direction