Virtual functions are a great feature, but they have a rather severe limitation. They can only be implemented by extending the definition of all classes involved. A lot of operations on classes don’t need to be members, and sticking them in the class, just to use virtual dispatching, leads to interface pollution. I’m proposing here an out-of-class virtual dispatching syntax.

The basic problem

In my Leaf compiler code I have an object of type expression , which could one of several sub-types. I wish to do some processing on this object. Some of the sub-types, not necessarily all, require special processing. Essentially I want to pass my object to one of these functions, depending on its type:

1 2 3 void process ( expression ) void process ( expression_binary ) void process ( expression_function )

There are two basic approaches to this dispatch: visitors and switches.

A visitor pattern

If we’re willing to retrofit the types involved we can create a visitor pattern. Add a accept function to each type in the class hierarchy and then build a visitor object.

1 2 3 4 5 6 7 class process_visitor : expression_visitor { void visit ( expression ) void visit ( expression_binary ) void visit ( expression_function ) } object . accept ( process_visitor )

The problem here is that I haven’t avoided modifying the origin type. I need to add an accept function to the base and every derived class. If I forget to add the function to a newly derived class then it breaks.

It also requires some kind of expression_visitor interface to be defined. What exactly should that be? Usually it will contain a definition for all the subtypes of expression . But I don’t always want to override the processing for all expressions.

Due to its limited functionality and a lot of boilerplate code I tend not to use the pattern often.

A big old switch

The other common approach is a switch statement:

1 2 3 4 5 switch ( type_of ( object ) ) { case t_binary: ... case t_function: ... default : ... }

This requires some way to identify the types, either natively in the language, or with a custom type id. Additionally, the switch statements I’ve seen don’t deal well with a value hierarchy. We can’t easily select a sub-tree of the type, instead we’re forced to itemize every leaf type. For this reason a series of if statements is often used instead.

1 2 3 4 5 6 if ( object instanceof expression_binary ) ) { ... } else if ( object instanceof expression_function ) ) { ... } else { }

This is a lot of repetitive coding, and it’s possible to get the order of the if statements wrong (like checking for a base type prior to a derived type).

Standalone virtual functions

Both approaches are just workarounds for what I really want: standalone virtual functions. I just want to express a series of functions with a common name that accept different types:

1 2 3 void process ( virtual expression & ) = 0 ; void process ( virtual expression_binary & b ); void process ( virtual expression_funccall & f );

The virtual bit expresses that dispatch to this overload is done based on the runtime type of the first parameter. I call this just as any other overloaded function:

1 process ( object );

At run-time the dispatch will be done to the function best matching the type: following the overload rules as though it were a static dispatch with the most derived type.

This has several advantages over the other approaches:

it is very compact without repetitive boilerplate code

the original types are left unmodified

it can dispatch over a subset of all the derived types

it doesn’t require a user-defined type identifier

it can deal with dispatching to mid-level types, not just leaf types

This feature would be a great addition to any OOP language with virtual functions. It’s a simple way to extend classes without touching the classes themselves.

If like to explore languages and compilers then follow me on Twitter. I always have more ideas and things to uncover. If there’s something special you’d like to hear about, or want to arrange a presentation feel free to contact me.