Dispatching on a variant

Jeremie Pelletier jeremiep at gmail.com
Sat Sep 26 09:25:23 PDT 2009


Justin Johansson wrote:
> language_fan Wrote:
> 
>> Sat, 26 Sep 2009 09:32:55 -0400, Justin Johansson thusly wrote:
>>
>>> I've had a good poke around the forums and couldn't find anything on
>>> this so ...
>>>
>>> What's the recommended method for dispatching code off the runtime type
>>> of a variant variable (Phobos D2 std.variant)?
>>>
>>> Does one use a bunch of
>>>
>>> if ( var.peek!(type1)) { ... }
>>> else if ( var.peek!(type2)  { ... }
>>>
>>> for all N possible types, or is there a better & faster way with a
>>> switch or jump table of sorts?
>> If the type count gets large, how fast it is depends on the backend 
>> optimizations of the compiler. In the worst case it is a O(n) time linear 
>> search. A jump table or almost any other way of dispatching would be 
>> faster. If the variant had an integral tag field, it could be used in a 
>> switch; that way the compiler could easily optimize it further with the 
>> currently available constructs.
>>
>> This problem is solved in higher level languages by providing pattern 
>> matching constructs. The compiler is free to optimize the code the way it 
>> likes:
>>
>>   case var of
>>     type1 => ...
>>     type2 => ...
>>     ...
>>
>> But since no C-like language has ever implemented pattern matching, it 
>> might be too radical to add it to D.
> 
> Thanks both for replies.
> 
> I've got about 2 dozen types in the variant so the O(n) really hurts.
> The variant thing seemed like a really cool idea at the time but now ...
> Without something like suggested above or a computed goto on typeid or Andrei's visitator,
> it almost pushes me to backout from using variants and having to redesign around some common base class or interface and using virtual function dispatch. :-(
> 

I see this sort of design in C all the time with event handling, 
although its with unions rather than discriminated unions, the same 
logic applies.

enum EventType {
	Mouse,
	Key,
	Move,
	...
}
struct Event {
	EventType type;
	union {
		MouseEvent mouse;
		KeyEvent key;
		MoveEvent move;
		...
	}
}

void dispatchEvent(const(Event)* event) {
	...
	with(EventType) final switch(event.type) {
	case Mouse: ...
	case Key: ...
	case Move: ...
	...
	}
	...
}

That's the logic with standard unions, you should be able to get 
something similar with variants. It's more code to setup, but you end up 
with a simple jump table from the switch, and final in D makes it easy 
to change EventType without forgetting to update dispatchEvent.



More information about the Digitalmars-d mailing list