Spec-Zone.ru › D

std.exception

В этом модуле определены функции, связанные с исключениями и обработкой ошибок в общем случае. Также определены функции, предназначенные для помощи в тестировании юнит-тестами.

Категория Функции
Предположения assertNotThrown assertThrown assumeUnique assumeWontThrow mayPointTo
Принудительное выполнение doesPointTo enforce errnoEnforce
Обработчики collectException collectExceptionMsg ifThrown handle
Прочие basicExceptionCtors emptyExceptionMsg ErrnoException RangePrimitive

Лицензия:
Boost License 1.0
Авторы:
Andrei Alexandrescu и Jonathan M Davis
Источник
std/exception.d
Примеры:
Описание
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__);

Утверждает, что заданный выражение не вызывает заданный тип Throwable. Если выбрасывается Throwable заданного типа, он перехватывается и не выходит за пределы assertNotThrown. Вместо этого выбрасывается AssertError. Однако любые другие Throwable будут выходить за пределы.

Параметры:
T Тип Throwable для проверки.
E expression Выражение для проверки.
string msg Необязательное сообщение для вывода при ошибке теста. Если msg пусто, а у исключения, вызванного исключением, есть поле msg отличное от пустого, поле msg исключения будет выведено при ошибке теста.
string file Файл, в котором произошла ошибка. По умолчанию __FILE__.
size_t line Строка, в которой произошла ошибка. По умолчанию __LINE__.
Исключения:
AssertError если заданный Throwable выброшен.
Возвращает:
результат expression.
Примеры:
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__);

Утверждает, что заданное выражение выбрасывает исключение заданного типа Throwable. Throwable перехватывается и не выходит за пределы assertThrown. Однако любые другие Throwable будут выходить за пределы, и если исключение заданного типа не выброшено, то будет выброшено AssertError.

Параметры:
T Тип Throwable для проверки.
E expression Выражение для проверки.
string msg Необязательное сообщение для вывода при ошибке теста.
string file Файл, в котором произошла ошибка. По умолчанию __FILE__.
size_t line Строка, в которой произошла ошибка. По умолчанию __LINE__.
Исключения:
AssertError если заданный Throwable не выброшен.
Примеры:
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);

Проверяет, что заданное значение истинно. Если заданное значение ложно, выбрасывается исключение.

  • msg - сообщение об ошибке в виде string
  • dg - пользовательский делегат, возвращающий строку и вызываемый только при возникновении исключения
  • ex - пользовательское исключение для выбрасывания. Оно lazy и создаётся только при возникновении исключения

Параметры:
T value Значение для проверки.
E Тип исключения, который будет выброшен, если значение ложно.
const(char)[] msg Сообщение об ошибке для включения в исключение, если оно будет выброшено.
Dg dg Делегат, который будет вызван, если значение ложно.
Throwable ex Исключение, которое будет выброшено, если значение ложно.
string file Файл источника вызывающей функции.
size_t line Номер строки вызывающей функции.
Возвращает:
value, если cast(bool) value истинно. В противном случае, в зависимости от выбранной перегрузки, выбрасывается new Exception(msg), dg() или ex.
Примечание
enforce используется для выбрасывания исключений и поэтому предназначен для обработки ошибок. Он не предназначен для проверки логики вашей программы. Для этого предназначен assert . Также не используйте enforce внутри контрактов (т.е. внутри in и out блоков и invariant), потому что контракты компилируются при компиляции с -release.
Если передаётся делегат, безопасность и чистота этой функции выведены из безопасности и чистоты Dg.
Примеры:
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);
Примеры:
assertNotThrown(enforce(true, new Exception("this should not be thrown")));
assertThrown(enforce(false, new Exception("this should be thrown")));
Примеры:
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
}
Примеры:
Алиасите вашу собственную функцию enforce
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) { } } )));

Проверяет, что заданное значение истинно, выбрасывая ErrnoException если это не так.

Параметры:
T value Значение для проверки.
const(char)[] msg Сообщение для включения в ErrnoException если оно выбрасывается.
Возвращает:
value, если cast(bool) value истинно. В противном случае выбрасывается new ErrnoException(msg). Предполагается, что последняя операция установила errno в код ошибки, соответствующий невыполнению условия.
Примеры:
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))))

Устарело. Пожалуйста, используйте enforce вместо этого. Эта функция будет удалена в версии 2.089.

Если !value равно false, возвращается value. В противном случае выбрасывается new E(msg, file, line). Или если E не принимает сообщение и может быть сконструирован с new E(file, line), то будет выброшено new E(file, line).

Пример
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__);

То же самое

T collectException(T = Exception, E)(lazy E expression, ref E result);

Перехватывает и возвращает исключение, выброшенное из заданного выражения. Если исключение не выбрасывается, то возвращается null, а result устанавливается в результат выражения.

Обратите внимание, что хотя collectException может использоваться для сбора любых Throwable и не только Exceptions, в целом не рекомендуется перехватывать что-либо, что не является Exception или типом, производным от Exception. Поэтому не используйте collectException для сбора не-Exceptions, если вы не уверены, что это то, что вы действительно хотите сделать.

Параметры:
T Тип исключения для перехвата.
E expression Выражение, которое может выбросить исключение.
E result Результат выражения, если исключение не выбрасывается.
Примеры:
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);

Перехватывает и возвращает исключение, выброшенное из заданного выражения. Если исключение не выбрасывается, возвращается null. E может быть void.

Обратите внимание, что хотя collectException может использоваться для сбора любых Throwable и не только Exceptions, в целом не рекомендуется перехватывать что-либо, что не является Exception или типом, производным от Exception. Поэтому не используйте collectException для сбора не-Exceptions, если вы не уверены, что это то, что вы действительно хотите сделать.

Параметры:
T Тип исключения для перехвата.
E expression Выражение, которое может выбросить исключение.
Примеры:
int foo() { throw new Exception("blah"); }
writeln(collectException(foo()).msg); // "blah"
string collectExceptionMsg(T = Exception, E)(lazy E expression);

Перехватывает исключение, выброшенное из заданного выражения, и возвращает свойство msg этого исключения. Если исключение не выбрасывается, возвращается null. E может быть void.

Если исключение выброшено, но оно имеет пустое сообщение, возвращается emptyExceptionMsg.

Обратите внимание, что хотя collectExceptionMsg может использоваться для сбора любых Throwable и не только Exceptions, в целом не рекомендуется перехватывать что-либо, что не является Exception или типом, производным от Exception. Поэтому не используйте collectExceptionMsg для сбора не-Exceptions, если вы не уверены, что это то, что вы действительно хотите сделать.

Параметры:
T Тип исключения для перехвата.
E expression Выражение, которое может выбросить исключение.
Примеры:
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;

Значение, которое collectExceptionMsg возвращает, когда перехватывает исключение с пустым сообщением об исключении.

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);

Преобразует изменяемый массив в неизменяемый массив идиоматичным способом. Технически, assumeUnique просто вставляет преобразование, но его имя документирует предположения со стороны вызывающего кода. assumeUnique(arr) следует вызывать только тогда, когда больше нет активных изменяемых ссылок на элементы arr. Для усиления этого предположения, assumeUnique(arr) также очищает arr перед возвратом. В сущности assumeUnique(arr) указывает обязательство вызывающего кода о том, что больше нет изменяемого доступа к элементам arr (переходно), и что все будущие обращения будут выполняться через возвращаемый неизменяемый массив assumeUnique.

Обычно assumeUnique используется для возвращения массивов из функций, которые их выделили и построили.

Параметры:
T[] array Массив, который нужно преобразовать в неизменяемый.
Возвращает:
Неизменяемый массив.
Пример
string letters()
{
  char[] result = new char['z' - 'a' + 1];
  foreach (i, ref e; result)
  {
    e = cast(char)('a' + i);
  }
  return assumeUnique(result);
}
Использование в примере выше верно, потому что result было приватным для letters и недоступно для записи после возврата функции. Следующий пример показывает неправильное использование assumeUnique.
Неправильно
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
}
Пример выше создаёт проблемы в клиентском коде, потому что он изменяет массивы, которые вызывающий код посчитал неизменяемыми. Для получения неизменяемого массива из изменяемого массива buffer, замените последнюю строку на:
return to!(string)(sneaky); // not that sneaky anymore
Вызов будет дублировать массив должным образом. Обратите внимание, что проверка уникальности во время компиляции возможна в определённых случаях, особенно когда функция помечена как чистая функция. Следующий пример не нуждается в вызове assumeUnique, потому что компилятор может определить уникальность массива в чистой функции:
string letters() pure
{
  char[] result = new char['z' - 'a' + 1];
  foreach (i, ref e; result)
  {
    e = cast(char)('a' + i);
  }
  return result;
}
Дополнительные сведения об определении уникальности см. в ключевых словах unique и lent в языке ArchJava. Недостатком использования соглашения о применении assumeUnique является то, что в настоящее время нет формальной проверки корректности предположения; с другой стороны, идиоматическое использование assumeUnique простое и достаточно редкое, чтобы быть терпимым.
Примеры:
int[] arr = new int[1];
auto arr1 = arr.assumeUnique;
static assert(is(typeof(arr1) == immutable(int)[]));
writeln(arr); // null
writeln(arr1); // [0]
Примеры:
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__);

Оборачивает потенциально выбрасывающее выражение в обёртку nothrow таким образом, что его можно вызвать из функции nothrow.

Эта функция-обёртка документирует обязательство со стороны вызывающего кода о том, что были предприняты необходимые шаги для предотвращения любых условий, которые могут вызвать исключение во время вычисления expr. Если окажется, что выражение выбрасывает исключение во время выполнения, обёртка выбросит исключение AssertError.

(Обратите внимание, что объекты Throwable такие как AssertError, которые не являются подклассом Exception, могут быть выброшены даже из функций nothrow, поскольку они считаются серьёзными проблемами во время выполнения, из которых невозможно восстановиться.)

Параметры:
T expr Выражение, которое, как утверждается, не выбросит исключение.
string msg Сообщение, которое следует включить в AssertError если предположение окажется ложным.
string file Имя файла вызывающего кода.
size_t line Номер строки вызывающего кода.
Возвращает:
Значение expr, если таковое имеется.
Примеры:
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);

Проверяет, содержит ли объект source указатели или ссылки на объект target.

Параметры:
S source Объект source
T target Объект target
Ошибки:
Функция явно помечена @nogc из-за возможного сбоя вывода, см. проблему 17084.
Возвращает:
true если представление source содержит указатель, который указывает на представление target или где-то внутри него. Если source является или содержит динамический массив, то эти функции проверяют, есть ли перекрытие между динамическим массивом и представлением target. Если source является классом, то он будет обрабатываться как указатель. Если target является указателем, динамическим массивом или классом, то эти функции проверяют только, указывает ли source на target, а не на то, что ссылается target. Если source является или содержит объединение или void[n], могут возникнуть либо ложные срабатывания, либо ложные отказы: doesPointTo вернёт true, если абсолютно точно, что source указывает на target. Она может давать ложные отказы, но никогда не ложные срабатывания. Эта функция предпочтительна при проверке входных данных. mayPointTo вернёт false, если абсолютно точно, что source не указывает на target. Она может давать ложные срабатывания, но никогда не ложные отказы. Эта функция предпочтительна для защитного выбора кода.
Примечание
Вычисление doesPointTo(x, x) проверяет, содержит ли x внутренние указатели. Это следует делать только как проверочное тестирование, поскольку язык свободен предполагать, что объекты не содержат внутренних указателей (TDPL 7.1.3.5).
Примеры:
Указатели
int  i = 0;
int* p = null;
assert(!p.doesPointTo(i));
p = &i;
assert( p.doesPointTo(i));
Примеры:
Структуры и объединения
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
Примеры:
Массивы (динамические и статические)
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));
Примеры:
Классы
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;

Выбрасывается при возникновении ошибок, которые устанавливают errno.

Примеры:
import core.stdc.errno : EAGAIN;
auto ex = new ErrnoException("oh no", EAGAIN);
writeln(ex.errno); // EAGAIN
Примеры:
errno используется по умолчанию, если явное кодовое значение ошибки не предоставлено
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();

Код ошибки операционной системы.

@safe this(string msg, string file = null, size_t line = 0);

Конструктор, который принимает сообщение об ошибке. Текущее глобальное значение core.stdc.errno.errno используется в качестве кода ошибки.

@safe this(string msg, int errno, string file = null, size_t line = 0);

Конструктор, который принимает сообщение об ошибке и код ошибки.

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. Выполняет предоставленное выражение и возвращает его результат. Если выражение выбросит Throwable, выполняет предоставленный обработчик ошибок вместо этого и возвращает его результат. Тип обработчика ошибок должен быть таким же, как тип выражения.

Параметры:
E Тип исключений для перехвата. По умолчанию Exception
T1 Тип выражения.
T2 Тип возвращаемого значения обработчика ошибок.
T1 expression Выражение, которое нужно выполнить и вернуть его результат.
T2 errorHandler Обработчик, который нужно выполнить, если выражение выбросило исключение.
Возвращает:
выражение, если оно не выбросит исключение. В противном случае возвращает результат errorHandler.
Примеры:
Возврат к значению по умолчанию при возникновении ошибки:
import std.conv : to;
writeln("x".to!int.ifThrown(0)); // 0
Примеры:
Цепочка нескольких вызовов ifThrown, каждый из которых перехватывает ошибки из всего предыдущего выражения.
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"
Примеры:
Выражение и errorHandler должны иметь общий тип, к которому оба могут быть неявным образом приведённы, и этот тип будет типом составного выражения.
// 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)));
Примеры:
Использование лямбда-функции для получения выброшенного объекта.
import std.format : format;
// "std.format.FormatException"
writeln("%s".format.ifThrown!Exception(e => e.classinfo.name));
enum RangePrimitive: int;

Этот enum используется для выбора примитивов диапазона, которые должны обрабатываться оболочкой диапазона handle. Значения enum могут быть OR для выбора нескольких примитивов для обработки.

RangePrimitive.access — это сокращение для доступа к примитивам; front, back и opIndex.

RangePrimitive.pop — это сокращение для примитивов изменения; popFront и popBack.

Примеры:
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]));
Примеры:
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

доступ

удаление
auto handle(E : Throwable, RangePrimitive primitivesToHandle, alias handler, Range)(Range input)
Constraints: if (isInputRange!Range);

Обработка исключений, выброшенных примитивами диапазона.

Используйте перечисление RangePrimitive для указания примитивов, которые нужно обработать. Несколько примитивов диапазона могут обрабатываться одновременно с помощью оператора OR или псевдопримитивов RangePrimitive.access и RangePrimitive.pop. Все обрабатываемые примитивы должны иметь типы возвращаемых значений или сами возвращаемые значения, совместимые с предоставленным пользователем обработчиком.

Параметры:
E Тип обрабатываемого Throwable.
primitivesToHandle Набор примитивов диапазона для обработки.
handler Вызываемый объект, который вызывается, когда обрабатываемый примитив выбрасывает Throwable типа E. Обработчик должен принимать аргументы в формате E, ref IRange и его возвращаемое значение используется в качестве возвращаемого значения примитива всякий раз, когда выбрасывается E. Для opIndex, обработчик может необязательно получить третий аргумент; индекс, вызвавший исключение.
Range input Диапазон для обработки.
Возвращаемое значение:
Оболочка struct , сохраняющая интерфейс диапазона input.
Примечание
Бесконечные диапазоны с поддержкой срезов должны возвращать экземпляр std.range.Take при срезе с определенным нижним и верхним пределом (см. std.range.primitives.hasSlicing); handle обрабатывает это, take 0 из возвращаемого значения функции-обработчика и возвращает это значение при перехвате исключения.
Примеры:
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]));
Примеры:
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()

Удобный миксин для тривиального наследования исключений

Даже тривиальное наследование исключения включает в себя написание шаблонного кода для конструктора, чтобы: 1) правильно передать имя файла и строку, в которой было сгенерировано исключение; 2) быть совместимым с enforce, который ожидает, что конструкторы исключений будут принимать аргументы в фиксированном порядке. Этот миксин предоставляет этот шаблонный код.

Обратите внимание, что вам необходимо пометить строку mixin по крайней мере минимальным (т.е. только ///) комментарием DDoc, если вы хотите, чтобы смешанные конструкторы были задокументированы в новом подклассе Exception.

Текущее ограничение: Из-за ошибки #11500, в настоящее время конструкторы, указанные в этом миксине, не могут быть перегружены какими-либо другими пользовательскими конструкторами. Таким образом, этот миксин в настоящее время может использоваться только в тех случаях, когда нет необходимости явно указывать такие пользовательские конструкторы.

Примеры:
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);
Параметры:
string msg Сообщение об исключении.
string file Файл, в котором возникло исключение.
size_t line Номер строки, в которой возникло исключение.
Throwable next Предыдущее исключение в цепочке исключений, если таковое имеется.
pure nothrow @nogc @safe this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__);
Параметры:
string msg Сообщение об исключении.
Throwable next Предыдущее исключение в цепочке исключений.
string file Файл, в котором возникло исключение.
size_t line Номер строки, в которой возникло исключение.

© 1999–2021 The D Language Foundation
Licensed under the Boost License 1.0.
https://dlang.org/phobos/std_exception.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API