Skip to content

Commit 25a59dd

Browse files
authored
[std.algorithm.comparison] Improve castSwitch docs (#10918)
Improve wording. Update docs & example for noreturn handler.
1 parent ff896d0 commit 25a59dd

File tree

1 file changed

+36
-25
lines changed

1 file changed

+36
-25
lines changed

std/algorithm/comparison.d

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -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
232235
Params:
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
239242
Returns:
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
*/
244245
auto 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

Comments
 (0)