Yowza, okay, I'm playing around with implementation of a little widget system. Now, normally virtuals and templates do NOT mix, but since in my case all instantiations would be explicit. G++ 3.3.3 is choking on this code:
struct context
{
void render( widget & w )
{
w.render( *this ); //immediately calls do_render
}
template < typename widget_type > virtual void do_render( widget_type * ) = 0; //<-- error
};
main.cc:23: error: invalid use of `virtual' in template declaration of `virtual
void context::do_render(widget_type*)'
Now, this is a bit of a bummer. Any workarounds that spring to mind? I wouldn't have though this would be a problem since IIRC vtable building occurs at link time... after all the instantiations would be available...
The basic idea is that context cannot determine the type of the widget, and thus asks the widget to render itself, as it knows what kind of widget it is. However, I wish to implement the rendering functions as templatized - but it dosn't seem to want to allow that. I'm seeing no obvious workaround. Any hints?
The basic idea is to allow a GUI widget set that is extensible without modifying headers. As is, I would have to manually add another virtual function to the context class, and then copy those changes to all versions of that class (opengl_context, sdl_context, etc etc etc). In this system, link errors would occur if used stuff was missing, but that's it:
widget name | used w/ base | implemented w/ derived | either
widget_1 | yes | no | yes
widget_2 | no | yes | yes
widget_3 | yes | yes | yes
widget_4 | no | no | no
base context vtable:
1 : do_render( widget_1 ) : throw by default ( to be caught if misrendered )
2 : do_render( widget_3 ) : throw by default ( to be caught if misrendered )
derived context vtable:
1 : do_render( widget_1 ) : inherited, not overridden (throws if we try and use since never implemented
2 : do_render( widget_3 ) : inherited, overridden (now does custom version since we implemented)
3 : do_render( widget_2 ) : new (custom version we implemented)
do_render( widget_4 ) is never included because we never have potential to use it.