@@ -215,31 +215,32 @@ private template indexOfFirstOvershadowingChoiceOnLast(choices...)
215215}
216216
217217/**
218- Executes and returns one of a collection of handlers based on the type of the
219- switch object.
218+ Executes one of a series of handlers based on the dynamic type of a class instance.
220219
221- The first choice that `switchObject` can be casted to the type
222- of argument it accepts will be called with `switchObject` casted to that
223- type, and the value it'll return will be returned by `castSwitch`.
224-
225- If a choice's return type is void, the choice must throw an exception, unless
226- all the choices are void. In that case, castSwitch itself will return void.
220+ $(P
221+ `switchObject`'s dynamic type is checked for compatibility with the argument type of each
222+ choice in turn until a match is found. When there's a match, the choice will be called with
223+ `switchObject` cast to that type. If the choice returns a value, `castSwitch` will return it.
224+ )
225+ - If one choice's return type is void and one can return a value, `SwitchError`
226+ will be thrown if the void handler was matched and completed execution without throwing.
227+ - A void handler is allowed to return when all the choices' return types convert to void -
228+ in that case, `castSwitch` itself will return void.
229+ - A choice's return type can be `noreturn` (e.g. when a handler always throws an exception).
227230
228- Throws: If none of the choice matches , a `SwitchError` will be thrown. $(D
229- SwitchError) will also be thrown if not all the choices are void and a void
230- choice was executed without throwing anything .
231+ Throws: If none of the choices match , a `SwitchError` will be thrown. $(D
232+ SwitchError) will also be thrown if one choice can return a value but a void
233+ choice was matched and completed execution .
231234
232235Params:
233- choices = The `choices` needs to be composed of function or delegate
234- handlers that accept one argument. There can also be a choice that
235- accepts zero arguments. That choice will be invoked if the $(D
236+ choices = A sequence of function and/ or delegate
237+ handlers that each accept one argument. There can also be one choice that
238+ accepts zero arguments, which will be invoked if the $(D
236239 switchObject) is null.
237240 switchObject = the object against which the tests are being made.
238241
239242Returns:
240- The value of the selected choice.
241-
242- Note: `castSwitch` can only be used with object types.
243+ The return value of the selected choice.
243244*/
244245auto castSwitch (choices... )(Object switchObject)
245246{
@@ -273,7 +274,7 @@ auto castSwitch(choices...)(Object switchObject)
273274 {
274275 alias CastClass = choiceParameterTypes[0 ];
275276 static assert (is (CastClass == class ) || is (CastClass == interface ),
276- " A choice handler can have only class or interface typed argument." );
277+ " A choice handler can only have a class or interface argument type ." );
277278
278279 // Check for overshadowing:
279280 immutable indexOfOvershadowingChoice =
@@ -384,8 +385,7 @@ auto castSwitch(choices...)(Object switchObject)
384385 class A
385386 {
386387 int a;
387- this (int a) {this .a = a;}
388- @property int i() { return a; }
388+ this (int a) { this .a = a; }
389389 }
390390 interface I { }
391391 class B : I { }
@@ -406,22 +406,33 @@ auto castSwitch(choices...)(Object switchObject)
406406 assert (results[2 ] == " null reference" );
407407}
408408
409- // / Using with void handlers:
409+ // / Using with noreturn/ void handlers:
410410@system unittest
411411{
412+ import core.exception : SwitchError ;
412413 import std.exception : assertThrown;
413414
414415 class A { }
415416 class B { }
416- // Void handlers are allowed if they throw:
417+
418+ // B's handler never returns, so `i` does not need a value
419+ int i;
417420 assertThrown! Exception (
418- new B ().castSwitch! (
421+ i = new B().castSwitch! (
422+ (A a) => 1 ,
423+ (B b) { throw new Exception (" B is not allowed!" ); }
424+ )()
425+ );
426+
427+ // Void handler call will throw if another handler returns a value
428+ assertThrown! SwitchError (
429+ i = new B().castSwitch! (
419430 (A a) => 1 ,
420- (B d) { throw new Exception ( " B is not allowed! " ); }
431+ (B b) { }
421432 )()
422433 );
423434
424- // Void handlers are also allowed if all the handlers are void:
435+ // Void handlers are allowed if all the handlers convert to void:
425436 new A ().castSwitch! (
426437 (A a) { },
427438 (B b) { assert (false ); },
0 commit comments