PROTOTYPEs, Grrr!

Previous topic - Next topic

bigsofty

I have a small problem with function prototypes. Every time I start to use them it completely breaks my way of coding, I normally do everything in Types, that is, as close as you can get to OO coding in GLB. So if I create a sprite type, I would have a type, with fields, various methods for updating, rendering, creating ect. It usually works great but function prototypes forces you to use static functions, that is create everything outside a type.

So this for example...

Code (glbasic) Select
PROTOTYPE EaseFuncProto#: t#

GLOBAL Ease AS TEase

TYPE TEase

EaseType[] AS EaseFuncProto

FUNCTION Linear#: t#; RETURN t; ENDFUNCTION

FUNCTION SetUp:
DIM self.EaseType[1]
self.EaseType[0] = self.Linear
ENDFUNCTION

ENDTYPE


Produces this compile error...

Code (glbasic) Select
C:\Users\Ian\AppData\Local\Temp\glbasic\gpc_tempg.cpp: In member function `DGInt __GLBASIC__::TEase::SetUp()':
C:\Users\Ian\AppData\Local\Temp\glbasic\gpc_tempg.cpp:2285: error: no match for 'operator=' in '(((__GLBASIC__::DGArray<__GLBASIC__::EaseFuncProto>*)((__GLBASIC__::TEase*)this)) + 4u)->__GLBASIC__::DGArray<T>::operator() [with T = __GLBASIC__::EaseFuncProto](0) = ((__GLBASIC__::TEase*)this)->__GLBASIC__::TEase::Linear'
C:/Program Files (x86)/GLBasic_v12/Compiler/platform/Include/glb.h:1530: note: candidates are: prototype __GLBASIC__::GLB_PROTO<prototype>::operator=(prototype) [with prototype = DGInt (*)(DGInt)]
C:/Program Files (x86)/GLBasic_v12/Compiler/platform/Include/glb.h:1527: note:                 __GLBASIC__::GLB_PROTO<DGInt (*)(DGInt)>& __GLBASIC__::GLB_PROTO<DGInt (*)(DGInt)>::operator=(const __GLBASIC__::GLB_PROTO<DGInt (*)(DGInt)>&)
*** FATAL ERROR - Please post this output in the forum


I can fix this by basically moving everything out of the type but boy is this messy. I don't see why it needs to be done at compile time as the function pointers can be assigned after a class has been created.

Any suggestion on how to keep PROTOTYPE functionality within the type?
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Slydog

#1
I had to check how I did my Easing Library - darn, no TYPE.
I just used simple constants to define the various eases available, such as:

Code (glbasic) Select
CONSTANT TWEEN_TYPE_LINEAR = 1
CONSTANT TWEEN_TYPE_QUAD_IN = 5
CONSTANT TWEEN_TYPE_CUBIC_IN = 8


Then a quick looked to get the desired value:
Code (glbasic) Select
FUNCTION Tween_Get: transition_type%, p1, p2, time
LOCAL p
SELECT transition_type
CASE TWEEN_TYPE_LINEAR; p = TweenTransition_Linear(p1, p2, time)
CASE TWEEN_TYPE_QUAD_IN; p = TweenTransition_QuadIn(p1, p2, time)
CASE TWEEN_TYPE_CUBIC_IN; p = TweenTransition_CubicIn(p1, p2, time)
ENDSELECT
RETURN p
ENDFUNCTION


Why is your EaseType[] an array?  Just curious. Wouldn't an instance of TEase be set to one specific Ease curve?
Wonder if it would work without an array.
Or, try removing the 'self.' portions, so it would be: EaseType[0] = Linear.
(In case the 'self' is throwing it off, although it may not like it.)

I've used PROTOTYPEs in a few places, mainly for callback events on my GUI (button.OnClick(), etc).
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

Slydog

#2
Here's where I used PROTOTYPEs for my Gui - buttons specifically:

Code (glbasic) Select
@PROTOTYPE PGui_Button_Click: id%

TYPE TGui_Button
xy[] AS TXyXy
fn_click AS PGui_Button_Click

@FUNCTION Set%: caption$, x%, y%, w%, fn_click AS PGui_Button_Click
// Removed other code for readability
self.fn_click = fn_click
ENDFUNCTION
ENDTYPE


This appears close to what your code is doing - I'm setting the prototype inside my TYPE.
One difference is I don't use an array (ha, don't think this is the problem), and the function that is passed is external to the TYPE.  You may have to have a separate TYPE for setting up your Eases, and one TYPE for implementing the Ease?  Just a thought.

[Edit] Not sure what the '@' symbols are for, been a long time.  It may just be to hide something from the navigation / jump panel to the right in the IDE.
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

bigsofty

#3
Hi Slydog,

Well the function pointer array is just a quicker way of selecting an ease via an indexed array. Its a little micro optimisation on using SELECT/CASE. I've used it to a certain extent in a recent easing library I posted earlier (see... http://www.glbasic.com/forum/index.php?topic=10097.0 ).

Your Type example is not quite the solution though, as you still can't set the function pointer to a function that resides within the type, "fn_click" must be a static function outside of a type somewhere within your program. You would still need "self." for a function (keep thinking 'method' each time I type this! :P) that is within the GLB type.

The C++ error kinda tells me what the problem is, that is that GLB prototyping is restricted to static functions. I was hoping that someone had found a way around this. I have considered doing the the declaration of the function pointer as inline C++ but I could not get the re-casting to work properly.

BTW I think your right, "@" used to hide a function from the Jump List.
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Kitty Hello

Pointer to member functions is not possible.

bigsofty

Lol, OK Gernot, that's kinda to the point.  :D

Do you think that this would be a possible addition at some point?
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Kitty Hello

No. C++ does not allow it. I mean if they were static (no self.xxx ) it would, but that would make GLB more complicated. I'd just use a function and start the name with the TYPE name...

bigsofty

Ah, oh well I can at least put this to bed, its something I've been coming back to many times thinking that I was not seeing the correct way to get it working.
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)