std.exception
This module defines functions related to exceptions and general error handling. It also defines functions intended to aid in unit testing.
Category | Functions |
---|---|
Assumptions | assertNotThrown assertThrown assumeUnique assumeWontThrow mayPointTo |
Enforce | doesPointTo enforce errnoEnforce |
Handlers | collectException collectExceptionMsg ifThrown handle |
Other | basicExceptionCtors emptyExceptionMsg ErrnoException RangePrimitive |
- License:
- Boost License 1.0
- Authors:
- Andrei Alexandrescu and Jonathan M Davis
- Source
- std/exception.d
- Examples:
- Synopis
import core.stdc.stdlib : malloc, free; import std.algorithm.comparison : equal; import std.algorithm.iteration : map, splitter; import std.algorithm.searching : endsWith; import std.conv : ConvException, to; import std.range : front, retro; // use enforce like assert int a = 3; enforce(a > 2, "a needs to be higher than 2."); // enforce can throw a custom exception enforce!ConvException(a > 2, "a needs to be higher than 2."); // enforce will return it's input enum size = 42; auto memory = enforce(malloc(size), "malloc failed")[0 .. size]; scope(exit) free(memory.ptr); // collectException can be used to test for exceptions Exception e = collectException("abc".to!int); assert(e.file.endsWith("conv.d")); // and just for the exception message string msg = collectExceptionMsg("abc".to!int); writeln(msg); // "Unexpected 'a' when converting from type string to type int" // assertThrown can be used to assert that an exception is thrown assertThrown!ConvException("abc".to!int); // ifThrown can be used to provide a default value if an exception is thrown writeln("x".to!int().ifThrown(0)); // 0 // handle is a more advanced version of ifThrown for ranges auto r = "12,1337z32,54".splitter(',').map!(a => to!int(a)); auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0); assert(h.equal([12, 0, 54])); assertThrown!ConvException(h.retro.equal([54, 0, 12])); // basicExceptionCtors avoids the boilerplate when creating custom exceptions static class MeaCulpa : Exception { mixin basicExceptionCtors; } e = collectException((){throw new MeaCulpa("diagnostic message");}()); writeln(e.msg); // "diagnostic message" writeln(e.file); // __FILE__ writeln(e.line); // __LINE__ - 3 // assumeWontThrow can be used to cast throwing code into `nothrow` void exceptionFreeCode() nothrow { // auto-decoding only throws if an invalid UTF char is given assumeWontThrow("abc".front); } // assumeUnique can be used to cast mutable instance to an `immutable` one // use with care char[] str = " mutable".dup; str[0 .. 2] = "im"; immutable res = assumeUnique(str); writeln(res); // "immutable"
- auto assertNotThrown(T : Throwable = Exception, E)(lazy E expression, string msg = null, string file = __FILE__, size_t line = __LINE__);
-
Asserts that the given expression does not throw the given type of
Throwable
. If aThrowable
of the given type is thrown, it is caught and does not escape assertNotThrown. Rather, anAssertError
is thrown. However, any otherThrowable
s will escape.- Parameters:
T The Throwable
to test for.E expression
The expression to test. string msg
Optional message to output on test failure. If msg is empty, and the thrown exception has a non-empty msg field, the exception's msg field will be output on test failure. string file
The file where the error occurred. Defaults to __FILE__
.size_t line
The line where the error occurred. Defaults to __LINE__
.
- Throws:
-
AssertError
if the givenThrowable
is thrown.
- Returns:
- the result of
expression
.
- Examples:
-
import core.exception : AssertError; import std.string; assertNotThrown!StringException(enforce!StringException(true, "Error!")); //Exception is the default. assertNotThrown(enforce!StringException(true, "Error!")); assert(collectExceptionMsg!AssertError(assertNotThrown!StringException( enforce!StringException(false, "Error!"))) == `assertNotThrown failed: StringException was thrown: Error!`);
- void assertThrown(T : Throwable = Exception, E)(lazy E expression, string msg = null, string file = __FILE__, size_t line = __LINE__);
-
Asserts that the given expression throws the given type of
Throwable
. TheThrowable
is caught and does not escape assertThrown. However, any otherThrowable
s will escape, and if noThrowable
of the given type is thrown, then anAssertError
is thrown.- Parameters:
T The Throwable
to test for.E expression
The expression to test. string msg
Optional message to output on test failure. string file
The file where the error occurred. Defaults to __FILE__
.size_t line
The line where the error occurred. Defaults to __LINE__
.
- Throws:
-
AssertError
if the givenThrowable
is not thrown.
- Examples:
-
import core.exception : AssertError; import std.string; assertThrown!StringException(enforce!StringException(false, "Error!")); //Exception is the default. assertThrown(enforce!StringException(false, "Error!")); assert(collectExceptionMsg!AssertError(assertThrown!StringException( enforce!StringException(true, "Error!"))) == `assertThrown failed: No StringException was thrown.`);
- template enforce(E : Throwable = Exception) if (is(typeof(new E("", string.init, size_t.init)) : Throwable) || is(typeof(new E(string.init, size_t.init)) : Throwable))
T enforce(T, Dg, string file = __FILE__, size_t line = __LINE__)(T value, scope Dg dg)
Constraints: if (isSomeFunction!Dg && is(typeof(dg())) && is(typeof(() { if (!value) { } } )));
T enforce(T)(T value, lazy Throwable ex); -
Enforces that the given value is true. If the given value is false, an exception is thrown. The
-
msg
- error message as astring
-
dg
- custom delegate that return a string and is only called if an exception occurred -
ex
- custom exception to be thrown. It islazy
and is only created if an exception occurred
- Parameters:
T value
The value to test. E Exception type to throw if the value evaluates to false. const(char)[] msg The error message to put in the exception if it is thrown. Dg dg
The delegate to be called if the value evaluates to false. Throwable ex
The exception to throw if the value evaluates to false. string file The source file of the caller. size_t line The line number of the caller.
- Returns:
-
value
, ifcast(bool) value
is true. Otherwise, depending on the chosen overload,new Exception(msg)
,dg()
orex
is thrown.
- Note
-
enforce
is used to throw exceptions and is therefore intended to aid in error handling. It is not intended for verifying the logic of your program. That is whatassert
is for. Also, do not useenforce
inside of contracts (i.e. inside ofin
andout
blocks andinvariant
s), because contracts are compiled out when compiling with -release.
Dg
's safety and purity.- Examples:
-
import core.stdc.stdlib : malloc, free; import std.conv : ConvException, to; // use enforce like assert int a = 3; enforce(a > 2, "a needs to be higher than 2."); // enforce can throw a custom exception enforce!ConvException(a > 2, "a needs to be higher than 2."); // enforce will return it's input enum size = 42; auto memory = enforce(malloc(size), "malloc failed")[0 .. size]; scope(exit) free(memory.ptr);
- Examples:
-
assertNotThrown(enforce(true, new Exception("this should not be thrown"))); assertThrown(enforce(false, new Exception("this should be thrown")));
- Examples:
-
writeln(enforce(123)); // 123 try { enforce(false, "error"); assert(false); } catch (Exception e) { writeln(e.msg); // "error" writeln(e.file); // __FILE__ writeln(e.line); // __LINE__ - 7 }
- Examples:
- Alias your own enforce function
import std.conv : ConvException; alias convEnforce = enforce!ConvException; assertNotThrown(convEnforce(true)); assertThrown!ConvException(convEnforce(false, "blah"));
- T enforce(T)(T value, lazy const(char)[] msg = null, string file = __FILE__, size_t line = __LINE__)
Constraints: if (is(typeof(() { if (!value) { } } )));
-
- alias errnoEnforce = enforce!(ErrnoException).enforce(T)(T value, lazy const(char)[] msg = null, string file = __FILE__, size_t line = __LINE__) if (is(typeof(() { if (!value) { } } )));
-
Enforces that the given value is true, throwing an
ErrnoException
if it is not.- Parameters:
T value The value to test. const(char)[] msg The message to include in the ErrnoException
if it is thrown.
- Returns:
-
value
, ifcast(bool) value
is true. Otherwise,new ErrnoException(msg)
is thrown. It is assumed that the last operation seterrno
to an error code corresponding with the failed condition.
- Examples:
-
import core.stdc.stdio : fclose, fgets, fopen; import std.file : thisExePath; import std.string : toStringz; auto f = fopen(thisExePath.toStringz, "r").errnoEnforce; scope(exit) fclose(f); char[100] buf; auto line = fgets(buf.ptr, buf.length, f); enforce(line !is null); // expect a non-empty line
- template enforceEx(E : Throwable) if (is(typeof(new E("", string.init, size_t.init))))
-
Deprecated. Please use
enforce
instead. This function will be removed 2.089.If
!value
isfalse
,value
is returned. Otherwise,new E(msg, file, line)
is thrown. Or ifE
doesn't take a message and can be constructed withnew E(file, line)
, thennew E(file, line)
will be thrown.- Example
auto f = enforceEx!FileMissingException(fopen("data.txt")); auto line = readln(f); enforceEx!DataCorruptionException(line.length);
- T enforceEx(T)(T value, lazy string msg = "", string file = __FILE__, size_t line = __LINE__);
-
Ditto
- T collectException(T = Exception, E)(lazy E expression, ref E result);
-
Catches and returns the exception thrown from the given expression. If no exception is thrown, then null is returned and
result
is set to the result of the expression.Note that while
collectException
can be used to collect anyThrowable
and not justException
s, it is generally ill-advised to catch anything that is neither anException
nor a type derived fromException
. So, do not usecollectException
to collect non-Exception
s unless you're sure that that's what you really want to do.- Parameters:
T The type of exception to catch. E expression
The expression which may throw an exception. E result
The result of the expression if no exception is thrown.
- Examples:
-
int b; int foo() { throw new Exception("blah"); } assert(collectException(foo(), b)); int[] a = new int[3]; import core.exception : RangeError; assert(collectException!RangeError(a[4], b));
- T collectException(T : Throwable = Exception, E)(lazy E expression);
-
Catches and returns the exception thrown from the given expression. If no exception is thrown, then null is returned.
E
can bevoid
.Note that while
collectException
can be used to collect anyThrowable
and not justException
s, it is generally ill-advised to catch anything that is neither anException
nor a type derived fromException
. So, do not usecollectException
to collect non-Exception
s unless you're sure that that's what you really want to do.- Parameters:
T The type of exception to catch. E expression
The expression which may throw an exception.
- Examples:
-
int foo() { throw new Exception("blah"); } writeln(collectException(foo()).msg); // "blah"
- string collectExceptionMsg(T = Exception, E)(lazy E expression);
-
Catches the exception thrown from the given expression and returns the msg property of that exception. If no exception is thrown, then null is returned.
E
can bevoid
.If an exception is thrown but it has an empty message, then
emptyExceptionMsg
is returned.
Note that whilecollectExceptionMsg
can be used to collect anyThrowable
and not justException
s, it is generally ill-advised to catch anything that is neither anException
nor a type derived fromException
. So, do not usecollectExceptionMsg
to collect non-Exception
s unless you're sure that that's what you really want to do.- Parameters:
T The type of exception to catch. E expression
The expression which may throw an exception.
- Examples:
-
void throwFunc() { throw new Exception("My Message."); } writeln(collectExceptionMsg(throwFunc())); // "My Message." void nothrowFunc() {} assert(collectExceptionMsg(nothrowFunc()) is null); void throwEmptyFunc() { throw new Exception(""); } writeln(collectExceptionMsg(throwEmptyFunc())); // emptyExceptionMsg
- enum string emptyExceptionMsg;
-
Value that collectExceptionMsg returns when it catches an exception with an empty exception message.
- pure nothrow immutable(T)[] assumeUnique(T)(T[] array);
pure nothrow immutable(T)[] assumeUnique(T)(ref T[] array);
pure nothrow immutable(T[U]) assumeUnique(T, U)(ref T[U] array); -
Casts a mutable array to an immutable array in an idiomatic manner. Technically,
assumeUnique
just inserts a cast, but its name documents assumptions on the part of the caller.assumeUnique(arr)
should only be called when there are no more active mutable aliases to elements ofarr
. To strengthen this assumption,assumeUnique(arr)
also clearsarr
before returning. EssentiallyassumeUnique(arr)
indicates commitment from the caller that there is no more mutable access to any ofarr
's elements (transitively), and that all future accesses will be done through the immutable array returned byassumeUnique
.Typically,
assumeUnique
is used to return arrays from functions that have allocated and built them.- Parameters:
T[] array
The array to cast to immutable.
- Returns:
- The immutable array.
- Example
string letters() { char[] result = new char['z' - 'a' + 1]; foreach (i, ref e; result) { e = cast(char)('a' + i); } return assumeUnique(result); }
The use in the example above is correct becauseresult
was private toletters
and is inaccessible in writing after the function returns. The following example shows an incorrect use ofassumeUnique
.- Bad
private char[] buffer; string letters(char first, char last) { if (first >= last) return null; // fine auto sneaky = buffer; sneaky.length = last - first + 1; foreach (i, ref e; sneaky) { e = cast(char)('a' + i); } return assumeUnique(sneaky); // BAD }
The example above wreaks havoc on client code because it is modifying arrays that callers considered immutable. To obtain an immutable array from the writable arraybuffer
, replace the last line with:return to!(string)(sneaky); // not that sneaky anymore
The call will duplicate the array appropriately. Note that checking for uniqueness during compilation is possible in certain cases, especially when a function is marked as a pure function. The following example does not need to call assumeUnique because the compiler can infer the uniqueness of the array in the pure function:string letters() pure { char[] result = new char['z' - 'a' + 1]; foreach (i, ref e; result) { e = cast(char)('a' + i); } return result; }
For more on infering uniqueness see the unique and lent keywords in the ArchJava language. The downside of usingassumeUnique
's convention-based usage is that at this time there is no formal checking of the correctness of the assumption; on the upside, the idiomatic use ofassumeUnique
is simple and rare enough to be tolerable.- Examples:
-
int[] arr = new int[1]; auto arr1 = arr.assumeUnique; static assert(is(typeof(arr1) == immutable(int)[])); writeln(arr); // null writeln(arr1); // [0]
- Examples:
-
int[string] arr = ["a":1]; auto arr1 = arr.assumeUnique; static assert(is(typeof(arr1) == immutable(int[string]))); writeln(arr); // null writeln(arr1.keys); // ["a"]
- nothrow T assumeWontThrow(T)(lazy T expr, string msg = null, string file = __FILE__, size_t line = __LINE__);
-
Wraps a possibly-throwing expression in a
nothrow
wrapper so that it can be called by anothrow
function.This wrapper function documents commitment on the part of the caller that the appropriate steps have been taken to avoid whatever conditions may trigger an exception during the evaluation of
expr
. If it turns out that the expression does throw at runtime, the wrapper will throw anAssertError
.
(Note thatThrowable
objects such asAssertError
that do not subclassException
may be thrown even fromnothrow
functions, since they are considered to be serious runtime problems that cannot be recovered from.)- Parameters:
T expr
The expression asserted not to throw. string msg
The message to include in the AssertError
if the assumption turns out to be false.string file
The source file name of the caller. size_t line
The line number of the caller.
- Returns:
- The value of
expr
, if any.
- Examples:
-
import std.math : sqrt; // This function may throw. int squareRoot(int x) { if (x < 0) throw new Exception("Tried to take root of negative number"); return cast(int) sqrt(cast(double) x); } // This function never throws. int computeLength(int x, int y) nothrow { // Since x*x + y*y is always positive, we can safely assume squareRoot // won't throw, and use it to implement this nothrow function. If it // does throw (e.g., if x*x + y*y overflows a 32-bit value), then the // program will terminate. return assumeWontThrow(squareRoot(x*x + y*y)); } writeln(computeLength(3, 4)); // 5
- pure nothrow @nogc @trusted bool doesPointTo(S, T, Tdummy = void)(auto ref const S source, ref const T target)
Constraints: if (__traits(isRef, source) || isDynamicArray!S || isPointer!S || is(S == class));
pure nothrow @trusted bool doesPointTo(S, T)(auto ref const shared S source, ref const shared T target);
pure nothrow @trusted bool mayPointTo(S, T, Tdummy = void)(auto ref const S source, ref const T target)
Constraints: if (__traits(isRef, source) || isDynamicArray!S || isPointer!S || is(S == class));
pure nothrow @trusted bool mayPointTo(S, T)(auto ref const shared S source, ref const shared T target); -
Checks whether a given source object contains pointers or references to a given target object.
- Parameters:
S source
The source object T target
The target object
- Bugs:
- The function is explicitly annotated
@nogc
because inference could fail, see issue 17084.
- Returns:
-
true
ifsource
's representation embeds a pointer that points totarget
's representation or somewhere inside it. Ifsource
is or contains a dynamic array, then, then these functions will check if there is overlap between the dynamic array andtarget
's representation. Ifsource
is a class, then it will be handled as a pointer. Iftarget
is a pointer, a dynamic array or a class, then these functions will only check ifsource
points totarget
, not whattarget
references. Ifsource
is or contains a union orvoid[n]
, then there may be either false positives or false negatives:doesPointTo
will returntrue
if it is absolutely certainsource
points totarget
. It may produce false negatives, but never false positives. This function should be prefered when trying to validate input data.mayPointTo
will returnfalse
if it is absolutely certainsource
does not point totarget
. It may produce false positives, but never false negatives. This function should be prefered for defensively choosing a code path.
- Note
- Evaluating
doesPointTo(x, x)
checks whetherx
has internal pointers. This should only be done as an assertive test, as the language is free to assume objects don't have internal pointers (TDPL 7.1.3.5).
- Examples:
- Pointers
int i = 0; int* p = null; assert(!p.doesPointTo(i)); p = &i; assert( p.doesPointTo(i));
- Examples:
- Structs and Unions
struct S { int v; int* p; } int i; auto s = S(0, &i); // structs and unions "own" their members // pointsTo will answer true if one of the members pointsTo. assert(!s.doesPointTo(s.v)); //s.v is just v member of s, so not pointed. assert( s.p.doesPointTo(i)); //i is pointed by s.p. assert( s .doesPointTo(i)); //which means i is pointed by s itself. // Unions will behave exactly the same. Points to will check each "member" // individually, even if they share the same memory
- Examples:
- Arrays (dynamic and static)
int i; // trick the compiler when initializing slice // https://issues.dlang.org/show_bug.cgi?id=18637 int* p = &i; int[] slice = [0, 1, 2, 3, 4]; int[5] arr = [0, 1, 2, 3, 4]; int*[] slicep = [p]; int*[1] arrp = [&i]; // A slice points to all of its members: assert( slice.doesPointTo(slice[3])); assert(!slice[0 .. 2].doesPointTo(slice[3])); // Object 3 is outside of the // slice [0 .. 2] // Note that a slice will not take into account what its members point to. assert( slicep[0].doesPointTo(i)); assert(!slicep .doesPointTo(i)); // static arrays are objects that own their members, just like structs: assert(!arr.doesPointTo(arr[0])); // arr[0] is just a member of arr, so not // pointed. assert( arrp[0].doesPointTo(i)); // i is pointed by arrp[0]. assert( arrp .doesPointTo(i)); // which means i is pointed by arrp // itself. // Notice the difference between static and dynamic arrays: assert(!arr .doesPointTo(arr[0])); assert( arr[].doesPointTo(arr[0])); assert( arrp .doesPointTo(i)); assert(!arrp[].doesPointTo(i));
- Examples:
- Classes
class C { this(int* p){this.p = p;} int* p; } int i; C a = new C(&i); C b = a; // Classes are a bit particular, as they are treated like simple pointers // to a class payload. assert( a.p.doesPointTo(i)); // a.p points to i. assert(!a .doesPointTo(i)); // Yet a itself does not point i. //To check the class payload itself, iterate on its members: () { import std.traits : Fields; foreach (index, _; Fields!C) if (doesPointTo(a.tupleof[index], i)) return; assert(0); }(); // To check if a class points a specific payload, a direct memmory check // can be done: auto aLoc = cast(ubyte[__traits(classInstanceSize, C)]*) a; assert(b.doesPointTo(*aLoc)); // b points to where a is pointing
- class ErrnoException: object.Exception;
-
Thrown if errors that set
errno
occur.- Examples:
-
import core.stdc.errno : EAGAIN; auto ex = new ErrnoException("oh no", EAGAIN); writeln(ex.errno); // EAGAIN
- Examples:
- errno is used by default if no explicit error code is provided
import core.stdc.errno : errno, EAGAIN; auto old = errno; scope(exit) errno = old; // fake that errno got set by the callee errno = EAGAIN; auto ex = new ErrnoException("oh no"); writeln(ex.errno); // EAGAIN
- final pure nothrow @nogc @property @safe uint errno();
-
Operating system error code.
- @safe this(string msg, string file = null, size_t line = 0);
-
Constructor which takes an error message. The current global
core.stdc.errno.errno
value is used as error code. - @safe this(string msg, int errno, string file = null, size_t line = 0);
-
Constructor which takes an error message and error code.
- CommonType!(T1, T2) ifThrown(E : Throwable = Exception, T1, T2)(lazy scope T1 expression, lazy scope T2 errorHandler);
CommonType!(T1, T2) ifThrown(E : Throwable, T1, T2)(lazy scope T1 expression, scope T2 delegate(E) errorHandler);
CommonType!(T1, T2) ifThrown(T1, T2)(lazy scope T1 expression, scope T2 delegate(Exception) errorHandler); -
ML-style functional exception handling. Runs the supplied expression and returns its result. If the expression throws a
Throwable
, runs the supplied error handler instead and return its result. The error handler's type must be the same as the expression's type.- Parameters:
E The type of Throwable
s to catch. Defaults toException
T1 The type of the expression. T2 The return type of the error handler. T1 expression
The expression to run and return its result. T2 errorHandler
The handler to run if the expression throwed.
- Returns:
- expression, if it does not throw. Otherwise, returns the result of errorHandler.
- Examples:
- Revert to a default value upon an error:
import std.conv : to; writeln("x".to!int.ifThrown(0)); // 0
- Examples:
- Chain multiple calls to ifThrown, each capturing errors from the entire preceding expression.
import std.conv : ConvException, to; string s = "true"; assert(s.to!int.ifThrown(cast(int) s.to!double) .ifThrown(cast(int) s.to!bool) == 1); s = "2.0"; assert(s.to!int.ifThrown(cast(int) s.to!double) .ifThrown(cast(int) s.to!bool) == 2); // Respond differently to different types of errors alias orFallback = (lazy a) => a.ifThrown!ConvException("not a number") .ifThrown!Exception("number too small"); writeln(orFallback(enforce("x".to!int < 1).to!string)); // "not a number" writeln(orFallback(enforce("2".to!int < 1).to!string)); // "number too small"
- Examples:
- The expression and the errorHandler must have a common type they can both be implicitly casted to, and that type will be the type of the compound expression.
// null and new Object have a common type(Object). static assert(is(typeof(null.ifThrown(new Object())) == Object)); static assert(is(typeof((new Object()).ifThrown(null)) == Object)); // 1 and new Object do not have a common type. static assert(!__traits(compiles, 1.ifThrown(new Object()))); static assert(!__traits(compiles, (new Object()).ifThrown(1)));
- Examples:
- Use a lambda to get the thrown object.
import std.format : format; // "std.format.FormatException" writeln("%s".format.ifThrown!Exception(e => e.classinfo.name));
- enum RangePrimitive: int;
-
This
enum
is used to select the primitives of the range to handle by thehandle
range wrapper. The values of theenum
can beOR
'd to select multiple primitives to be handled.RangePrimitive.access
is a shortcut for the access primitives;front
,back
andopIndex
.
RangePrimitive.pop
is a shortcut for the mutating primitives;popFront
andpopBack
.- Examples:
-
import std.algorithm.comparison : equal; import std.algorithm.iteration : map, splitter; import std.conv : to, ConvException; auto s = "12,1337z32,54,2,7,9,1z,6,8"; // The next line composition will throw when iterated // as some elements of the input do not convert to integer auto r = s.splitter(',').map!(a => to!int(a)); // Substitute 0 for cases of ConvException auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0); assert(h.equal([12, 0, 54, 2, 7, 9, 0, 6, 8]));
- Examples:
-
import std.algorithm.comparison : equal; import std.range : retro; import std.utf : UTFException; auto str = "hello\xFFworld"; // 0xFF is an invalid UTF-8 code unit auto handled = str.handle!(UTFException, RangePrimitive.access, (e, r) => ' '); // Replace invalid code points with spaces assert(handled.equal("hello world")); // `front` is handled, assert(handled.retro.equal("dlrow olleh")); // as well as `back`
-
front
back
popFront
popBack
empty
save
length
opDollar
opIndex
opSlice
access
pop
- auto handle(E : Throwable, RangePrimitive primitivesToHandle, alias handler, Range)(Range input)
Constraints: if (isInputRange!Range); -
Handle exceptions thrown from range primitives.
Use the
RangePrimitive
enum to specify which primitives to handle. Multiple range primitives can be handled at once by using theOR
operator or the pseudo-primitivesRangePrimitive.access
andRangePrimitive.pop
. All handled primitives must have return types or values compatible with the user-supplied handler.- Parameters:
E The type of Throwable
to handle.primitivesToHandle Set of range primitives to handle. handler The callable that is called when a handled primitive throws a Throwable
of typeE
. The handler must accept arguments of the formE, ref IRange
and its return value is used as the primitive's return value wheneverE
is thrown. ForopIndex
, the handler can optionally recieve a third argument; the index that caused the exception.Range input
The range to handle.
- Returns:
- A wrapper
struct
that preserves the range interface ofinput
.
- Note
- Infinite ranges with slicing support must return an instance of
std.range.Take
when sliced with a specific lower and upper bound (seestd.range.primitives.hasSlicing
);handle
deals with this bytake
ing 0 from the return value of the handler function and returning that when an exception is caught.
- Examples:
-
import std.algorithm.comparison : equal; import std.algorithm.iteration : map, splitter; import std.conv : to, ConvException; auto s = "12,1337z32,54,2,7,9,1z,6,8"; // The next line composition will throw when iterated // as some elements of the input do not convert to integer auto r = s.splitter(',').map!(a => to!int(a)); // Substitute 0 for cases of ConvException auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0); assert(h.equal([12, 0, 54, 2, 7, 9, 0, 6, 8]));
- Examples:
-
import std.algorithm.comparison : equal; import std.range : retro; import std.utf : UTFException; auto str = "hello\xFFworld"; // 0xFF is an invalid UTF-8 code unit auto handled = str.handle!(UTFException, RangePrimitive.access, (e, r) => ' '); // Replace invalid code points with spaces assert(handled.equal("hello world")); // `front` is handled, assert(handled.retro.equal("dlrow olleh")); // as well as `back`
- template basicExceptionCtors()
-
Convenience mixin for trivially sub-classing exceptions
Even trivially sub-classing an exception involves writing boilerplate code for the constructor to: 1) correctly pass in the source file and line number the exception was thrown from; 2) be usable with
enforce
which expects exception constructors to take arguments in a fixed order. This mixin provides that boilerplate code.
Note however that you need to mark the mixin line with at least a minimal (i.e. just ///) DDoc comment if you want the mixed-in constructors to be documented in the newly created Exception subclass.
Current limitation: Due to bug #11500, currently the constructors specified in this mixin cannot be overloaded with any other custom constructors. Thus this mixin can currently only be used when no such custom constructors need to be explicitly specified.- Examples:
-
class MeaCulpa: Exception { /// mixin basicExceptionCtors; } try throw new MeaCulpa("test"); catch (MeaCulpa e) { writeln(e.msg); // "test" writeln(e.file); // __FILE__ writeln(e.line); // __LINE__ - 5 }
- pure nothrow @nogc @safe this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null);
-
- Parameters:
string msg
The message for the exception. string file
The file where the exception occurred. size_t line
The line number where the exception occurred. Throwable next
The previous exception in the chain of exceptions, if any.
- pure nothrow @nogc @safe this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__);
-
- Parameters:
string msg
The message for the exception. Throwable next
The previous exception in the chain of exceptions. string file
The file where the exception occurred. size_t line
The line number where the exception occurred.
© 1999–2021 The D Language Foundation
Licensed under the Boost License 1.0.
https://dlang.org/phobos/std_exception.html