class
ConvException
:
object.Exception;
Исключение, бросаемое при ошибках преобразования.
class
ConvOverflowException
:
std.conv.ConvException;
Исключение, бросаемое при ошибках переполнения во время преобразования.
Шаблон to
преобразует значение из одного типа в другой. Исходный тип выводится, а целевой тип должен быть определен, например выражение to
!int(42.0) преобразует число 42 из
double в int. Преобразование является "безопасным", то есть, при нём происходит проверка на наличие переполнения; to
!int(4.2e10) должно бросить исключение
ConvOverflowException. Проверки переполнения включаются только когда необходимо, например, to
!double(42) не выполняет каких-либо проверок, поскольку любой int помещается в double.
Преобразования из строковых в числовые типы отличаются от эквивалентов из C
atoi() и
atol() проверкой на переполнение и тем, что не допускают пробелы.
Для преобразования строк в знаковые типы, общепризнанная грамматика такая:
Integer: Sign UnsignedInteger
UnsignedInteger
Sign:
+
-
Для преобразования строк в беззнаковые типы, общепризнанная грамматика такая:
UnsignedInteger:
DecimalDigit
DecimalDigit UnsignedInteger
Примеры: Преобразование значений в свой собственный тип (полезно по большей части для обобщённого кода), просто возвращает свой аргумент.
int a = 42;
int b = to!int(a);
double c = to!double(3.14);
Примеры: Преобразование между числовыми типами – безопасный способ использовать cast.
Преобразования из типов с плавающей точкой в целые типы допускают потерю точности (дробная часть чисел с плавающей точкой). Преобразование усекает в сторону нуля, точно так же усекал бы cast. (Чтобы округлять значения с плавающей точкой, преобразуя их в целые, используйте
roundTo.)
import std.exception : assertThrown;
int a = 420;
assert(to!long(a) == a);
assertThrown!ConvOverflowException(to!byte(a));
assert(to!int(4.2e6) == 4200000);
assertThrown!ConvOverflowException(to!uint(-3.14));
assert(to!uint(3.14) == 3);
assert(to!uint(3.99) == 3);
assert(to!int(-3.99) == -3);
Примеры: Заметьте, что D при преобразовании строк в числовые типы не обрабатывает шестнадцатеричные и двоичные литералы. Ни префиксы, которые указывают базу, ни горизонтальные подчеркивания, используемые для разделения групп цифр, не распознаются. Это также относится к суффиксам, которые указывают на тип.
Чтобы обойти эту проблему, вы можете определить основание для преобразований, связанных с числами.
auto str = to!string(42, 16);
assert(str == "2A");
auto i = to!int(str, 16);
assert(i == 42);
Примеры: Преобразования из целых типов в типы с плавающей точкой всегда удаются, но могут привести к потере точности. Самые большие целые, представимые в формате с плавающей точкой –
2^24-1 для
float,
2^53-1 для
double, и
2^64-1 для
real (когда
real – 80-битный, например, в машинах Intel).
int a = 16_777_215;
assert(to!int(to!float(a)) == a);
assert(to!int(to!float(-a)) == -a);
Примеры: Преобразование массива в массив другого типа работает через преобразование каждого элемента по очереди. Ассоциативные массивы, могут быть преобразованы в ассоциативные массивы, пока ключи и значения могут быть преобразованы в свою очередь.
import std.string : split;
int[] a = [1, 2, 3];
auto b = to!(float[])(a);
assert(b == [1.0f, 2, 3]);
string str = "1 2 3 4 5 6";
auto numbers = to!(double[])(split(str));
assert(numbers == [1.0, 2, 3, 4, 5, 6]);
int[string] c;
c["a"] = 1;
c["b"] = 2;
auto d = to!(double[wstring])(c);
assert(d["a"w] == 1 && d["b"w] == 2);
Примеры: Преобразования действуют транзитивно, а это означает, что они работают с массивами и ассоциативными массивами любой сложности.
Это преобразование работает, поскольку
to
!short относится к
int,
to
!wstring
относится к
string,
to
!string относится к
double, и
to
!(double[]) относится к
int[]. Преобразование может бросить исключение, поскольку
to
!short может потерпеть неудачу при контроле на переполнение.
int[string][double[int[]]] a;
auto b = to!(short[wstring][string[double[]]])(a);
Примеры: Преобразования объект-объект динамического приведения типа бросают исключение, если источник не-
null
, а цель –
null
.
import std.exception : assertThrown;
class A {}
class B : A {}
class C : A {}
A a1 = new A, a2 = new B, a3 = new C;
assert(to!B(a2) is a2);
assert(to!C(a3) is a3);
assertThrown!ConvException(to!B(a3));
Примеры: Поддерживаются строковые преобразования из любых типов.
- Преобразование строки в строку работает для любых двух типов строки, с любой шириной символа
(char, wchar, dchar) и с любой комбинацией квалификаторов (изменяемые, const, или immutable).
- Преобразования массивов (кроме строк) в строки. Каждый элемент преобразуется вызовом
to
!T.
- Преобразование ассоциативного массива в строку. Каждый элемент печатается вызовом
to
!T.
- Преобразование объекта в строку вызывает toString у объекта или возвращает "
null
", если объект – null
.
- Преобразование структуры в строку вызывает toString у структуры, если этот метод определён.
- Для структур, в которых не определён toString, преобразование в строку формирует список полей.
- Типы перечислений преобразуются в строки как их символические имена.
- Значения типа Boolean печатаются как "
true
" или "false
".
- char, wchar, dchar в строковый тип.
- Беззнаковые или знаковые целые в строки.
- [специальный случай]
- Преобразования целых значений в строки по основанию radix.
Основание должно быть величиной от 2 до 36.
Значения рассматриваются как знаковые, только если основание равно 10.
Символы от A до Z используются для представления значений от 10 до 36, и их регистр определяется параметром letterCase.
- Все типы с плавающей точкой во все типы строк.
- Преобразование указателя в строку печатает указатель как величину size_t.
Если указатель – это char*, он рассматривается как строка в C-стиле.
В таком случае, эта функция будет @system.
long[] a = [ 1, 3, 5 ];
assert(to!string(a) == "[1, 3, 5]");
int[string] associativeArray = ["0":1, "1":2];
assert(to!string(associativeArray) == `["0":1, "1":2]` ||
to!string(associativeArray) == `["1":2, "0":1]`);
assert(to!string(cast(char*) null) == "");
assert(to!string("foo\0".ptr) == "foo");
auto w = "abcx"w;
const(void)[] b = w;
assert(b.length == 8);
auto c = to!(wchar[])(b);
assert(c == "abcx");
Преобразование округления из чисел с плавающей точкой в целые.
Преобразования округления не работают с не-целыми целевыми типами.
Примеры: assert(roundTo!int(3.14) == 3);
assert(roundTo!int(3.49) == 3);
assert(roundTo!int(3.5) == 4);
assert(roundTo!int(3.999) == 4);
assert(roundTo!int(-3.14) == -3);
assert(roundTo!int(-3.49) == -3);
assert(roundTo!int(-3.5) == -4);
assert(roundTo!int(-3.999) == -4);
assert(roundTo!(const int)(to!(const double)(-3.999)) == -4);
Переместиться к: 2 · 3 · 4 · 5 · 6 · 7 · 8
Target
parse
(Target, Source)(ref Source
s
)
if (isInputRange!Source && isSomeChar!(ElementType!Source) && is(Unqual!Target == bool));
Семейство функций
parse
работает совсем как семейство
to, за исключением:
- Оно работает только с символьными диапазонами на входе.
- Оно принимает входные данные по ссылке. (Это означает, что rvalues – как например, литералы строк – не принимаются: используйте в таком случае to.)
- Оно продвигает вход в позицию после преобразования.
- Оно не бросает исключений, если не получилось преобразовать весь вход.
Эта перегрузка преобразует символьный входной диапазон в bool.
Параметры: Target |
тип, в который надо преобразовать |
Source s |
lvalue – входной диапазон |
Замечание:
Все преобразования символьных входных диапазонов, использующие to , перенаправляются к parse
и не требуют lvalues.
Примеры: auto s = "true";
bool b = parse!bool(s);
assert(b);
Target
parse
(Target, Source)(ref Source
s
)
if (isSomeChar!(ElementType!Source) && isIntegral!Target && !is(Target == enum));
Target
parse
(Target, Source)(ref Source
s
, uint
radix
)
if (isSomeChar!(ElementType!Source) && isIntegral!Target && !is(Target == enum));
Выполняет грамматический разбор символьного входного диапазона в целое значение.
Параметры: Target |
целый тип, в который надо преобразовать |
Source s |
lvalue – входной диапазон |
Возвращает: Число типа Target
Исключения: ConvException, если во время преобразования произошло переполнение, или если никакой входной символ не был значимо преобразован.
Примеры: string s = "123";
auto a = parse!int(s);
assert(a == 123);
static assert(!__traits(compiles, parse!int("123")));
Примеры: import std.string : munch;
string test = "123 \t 76.14";
auto a = parse!uint(test);
assert(a == 123);
assert(test == " \t 76.14"); munch(test, " \t\n\r"); assert(test == "76.14");
auto b = parse!double(test);
assert(b == 76.14);
assert(test == "");
Target
parse
(Target, Source)(ref Source
s
)
if (isSomeString!Source && !is(Source == enum) && is(Target == enum));
Принимает строку, представляющую тип enum и возвращает этот тип.
Параметры: Target |
Тип enum, в который надо преобразовать |
Source s |
lvalue – входной диапазон для разбора |
Возвращает: Перечисление типа Target
Примеры: enum EnumType : bool { a = true, b = false, c = a }
auto str = "a";
assert(parse!EnumType(str) == EnumType.a);
Target
parse
(Target, Source)(ref Source
p
)
if
(isInputRange!Source && isSomeChar!(ElementType!Source)
&& !is(Source == enum) && isFloatingPoint!Target
&& !is(Target == enum));
Выполняет грамматический разбор символьного диапазона в число с плавающей точкой.
Параметры: Target |
тип числа с плавающей точкой, в который надо преобразовать |
Source p |
lvalue – входной диапазон для разбора |
Возвращает: число с плавающей точкой типа Target
Исключения: ConvException, если
p
пуст, если число не разобрано, или если случилось переполнение.
Примеры: import std.math : approxEqual;
auto str = "123.456";
assert(parse!double(str).approxEqual(123.456));
Target
parse
(Target, Source)(ref Source
s
)
if
(isSomeString!Source && !is(Source == enum) &&
staticIndexOf!(Unqual!Target, dchar,
Unqual!(ElementEncodingType!Source)) >= 0);
Target
parse
(Target, Source)(ref Source
s
)
if
(!isSomeString!Source && isInputRange!Source &&
isSomeChar!(ElementType!Source) && isSomeChar!Target &&
Target.sizeof >= ElementType!Source.sizeof && !is(Target ==
enum));
Грамматический разбор одного символа из диапазона, возвращает первый элемент и вызывает popFront.
Параметры: Target |
тип, в который надо преобразовать |
Source s |
lvalue – входной диапазон |
Возвращает: Символьный тип Target
Примеры: auto s = "Hello, World!";
char first = parse!char(s);
assert(first == 'H');
assert(s == "ello, World!");
Target
parse
(Target, Source)(ref Source
s
)
if (isInputRange!Source && isSomeChar!(ElementType!Source) && is(Unqual!Target == typeof(null)));
Выполняет грамматический разбор символьного диапазона в typeof(null), возвращая null, если диапазон состоит из букв "null". Эта функция нечувствительна к регистру.
Параметры: Target |
тип, в который надо преобразовать |
Source s |
lvalue – входной диапазон |
Примеры: import std.exception : assertThrown;
alias NullType = typeof(null);
auto s1 = "null";
assert(parse!NullType(s1) is null);
assert(s1 == "");
auto s2 = "NUll"d;
assert(parse!NullType(s2) is null);
assert(s2 == "");
auto m = "maybe";
assertThrown!ConvException(parse!NullType(m));
assert(m == "maybe");
auto s = "NULL";
assert(parse!(const NullType)(s) is null);
Target
parse
(Target, Source)(ref Source
s
, dchar
lbracket
= '[', dchar
rbracket
= ']', dchar
comma
= ',')
if (isExactSomeString!Source && isDynamicArray!Target && !is(Target == enum));
Target
parse
(Target, Source)(ref Source
s
, dchar
lbracket
= '[', dchar
rbracket
= ']', dchar
comma
= ',')
if (isExactSomeString!Source && isStaticArray!Target && !is(Target == enum));
Выполняет грамматический разбор в массив из строки с передаваемыми левой скобкой (по-умолчанию '['), правой скобкой (по-умолчанию ']'), и разделителя элементов (по умолчанию ',').
Target
parse
(Target, Source)(ref Source
s
, dchar
lbracket
= '[', dchar
rbracket
= ']', dchar
keyval
= ':', dchar
comma
= ',')
if (isExactSomeString!Source && isAssociativeArray!Target && !is(Target == enum));
Выполняет грамматический разбор в ассоциативный массив из строки с передаваемыми левой скобкой (по-умолчанию '['), правой скобкой (по-умолчанию ']'), разделителя ключ-значение (по-умолчанию ':'), и разделителя элементов (по умолчанию ',').
string
text
(T...)(T
args
)
if (T.length > 0);
wstring
wtext
(T...)(T
args
)
if (T.length > 0);
dstring
dtext
(T...)(T
args
)
if (T.length > 0);
Удобные функции для преобразования одного или более аргументов любого типа в текст (три ширины символа).
Примеры: assert( text(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"c);
assert(wtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"w);
assert(dtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"d);
template
octal
(string num) if (isOctalLiteral(num))
template
octal
(alias decimalInteger) if (isIntegral!(typeof(decimalInteger)))
Объект octal
предоставляет средства объявлять числа с основанием 8.
Используйте octal
!177 или octal
!"177" для представления 127 в восьмиричном виде
(тоже, что 0177 в C).
Правила для строк обычные для литералов: если её можно преобразовать в
int,, то это – int. В противном случае, это long. Но, если пользователь специально требует long с помощью суффикса L, всегда даётся long. Беззнаковый тип даётся тогда и только тогда, когда есть требование через суффикс U или u. Восьмиричные числа, созданные из целых, сохраняют тип переданного целого.
Смотрите также: parse для синтаксического разбора строк, представляющих восьмеричные числа, во время выполнения.
Примеры: auto x = octal!177;
enum y = octal!160;
auto z = octal!"1_000_000u";
Переместиться к: 2 · 3 · 4
pure nothrow @safe T*
emplace
(T)(T*
chunk
);
Данный указатель на неинициализированную память chunk
(но уже типизированный в T), создает объект типа T, не являющегося классом, по этому адресу. Если T – это класс, инициализирует ссылку в null
.
Возвращает: Указатель на вновь созданный объект (что тоже самое, что и chunk
).
Примеры: static struct S
{
int i = 42;
}
S[2] s2 = void;
emplace(&s2);
assert(s2[0].i == 42 && s2[1].i == 42);
Примеры: interface I {}
class K : I {}
K k = void;
emplace(&k);
assert(k is null);
I i = void;
emplace(&i);
assert(i is null);
T*
emplace
(T, Args...)(T*
chunk
, auto ref Args
args
)
if (is(T == struct) || Args.length == 1);
Даётся указатель на неинициализированную память chunk
(но уже типизированный как тип T, не являющийся классом), создает объект типа T по этому адресу из аргументов args
. Если T – это класс, инициализирует ссылку класса на args
[0].
Эта функция может быть @trusted, если соответсвующий конструктор
T является @safe.
Возвращает: Указатель на вновь созданный объект (что тоже самое, что и chunk
).
Примеры: int a;
int b = 42;
assert(*emplace!int(&a, b) == 42);
T
emplace
(T, Args...)(void[]
chunk
, auto ref Args
args
)
if (is(T == class));
Даётся область сырой памяти chunk
, создается объект типа class
type T являющийся классом, по этому адресу. В конструктор передаются аргументы
Args.
Если T является внутренним классом, чье поле outer может использоваться для доступа к экземпляру включающего класса, то Args не должно быть пусто, и первым его членом должен быть правильный инциализатор для этого поля outer. Правильная инициализация этого поля имеет важное значение для доступа к членам внешнего класса внутри методов T.
Предусловия:
chunk
должен быть по крайней мере таким же большим как требуется T, и должен иметь выравнивание, кратное выравниванию T. (Размер экземпляра класса можно получить с использованием _traits(classInstanceSize, T)).
Замечание:
Эта функция может быть @trusted, если соответсвующий конструктор
T является @safe.
Возвращает: Вновь созданный объект.
Примеры: static class C
{
int i;
this(int i){this.i = i;}
}
auto buf = new void[__traits(classInstanceSize, C)];
auto c = emplace!C(buf, 5);
assert(c.i == 5);
T*
emplace
(T, Args...)(void[]
chunk
, auto ref Args
args
)
if (!is(T == class));
Даётся область сырой памяти chunk
, создает объект типа T, не являющийся классом, по этому адресу. Конструктору передаются аргументы args
, если имеются.
Предусловия:
chunk
должен быть по крайней мере таким же большим как требуется T, и должен иметь выравнивание, кратное выравниванию T.
Замечание:
Эта функция может быть @trusted, если соответсвующий конструктор
T является @safe.
Возвращает: Указатель на вновь созданный объект.
Примеры: struct S
{
int a, b;
}
auto buf = new void[S.sizeof];
S s;
s.a = 42;
s.b = 43;
auto s1 = emplace!S(buf, s);
assert(s1.a == 42 && s1.b == 43);
auto
unsigned
(T)(T
x
)
if (isIntegral!T);
Возвращает соответствующее беззнаковое значение для x
(например, если x
имеет тип
int, то будет возвращён cast(uint) x
). Преимущество по сравнению с cast в том, что вам не нужно переписывать cast, если впоследствии тип x
изменится (например, из int в long).
Заметьте, что результат - всегда изменяемый, даже если бы исходный тип был const или immutable. Для того, чтобы сохранить константность, используйте
std.traits.Unsigned.
Примеры: immutable int s = 42;
auto u1 = unsigned(s); static assert(is(typeof(u1) == uint));
Unsigned!(typeof(s)) u2 = unsigned(s); static assert(is(typeof(u2) == immutable uint));
immutable u3 = unsigned(s);
auto
signed
(T)(T
x
)
if (isIntegral!T);
Возвращает соответствующее знаковое значение для x
(например, если x
имеет тип
uint, то будет возвращён cast(int) x
). Преимущество по сравнению с cast в том, что вам не нужно переписывать cast, если впоследствии тип x
изменится (например, из uint в ulong).
Заметьте, что результат - всегда изменяемый, даже если бы исходный тип был const или immutable. Для того, чтобы сохранить константность, используйте
std.traits.Signed.
Примеры: immutable uint u = 42;
auto s1 = signed(u); static assert(is(typeof(s1) == int));
Signed!(typeof(u)) s2 = signed(u); static assert(is(typeof(s2) == immutable int));
immutable s3 = signed(u);
Обёртка поверх встроенного оператора cast, которая позволяет ограничить приведение по типу исходного значения.
Общая проблема с использованием сырого cast состоит в том, что он может молча продолжить компиляцию, даже если тип значения изменился во время рефакторинга, и нарушилось первоначальное предположение о cast.
Параметры: From |
Тип, из которого приводится. Программист должен гарантировать, что он легален для выполнения cast. |
ref @system auto
to
(To, T)(auto ref T
value
);
Параметры: To |
Тип, к которому приводится. |
T value |
Приводимое значение. Он должен быть типа From,
в противном случае выдаётся ошибка времени компиляции. |
Возвращает: значение после приведения, возвращённое ссылкой, если возможно.
Примеры: {
long x;
auto y = cast(int) x;
}
{
long* x;
auto y = cast(int) x;
}
{
long x;
auto y = castFrom!long.to!int(x);
}
{
long* x;
static assert (
!__traits(compiles, castFrom!long.to!int(x))
);
auto y = castFrom!(long*).to!int(x);
}
template
hexString
(string hexData) if (hexData.isHexLiteral)
template
hexString
(wstring hexData) if (hexData.isHexLiteral)
template
hexString
(dstring hexData) if (hexData.isHexLiteral)
Преобразует шестнадцатеричный литерал в строку во время компиляции.
Принимает строку, составленную из шестнадцатеричных цифр, и возвращает соответствующую строку, преобразуя каждую пару цифр в символ. Входная строка может также включать пробельные символы, которые могут быть использованы, чтобы удерживать строку с литералами в удобочитаемом виде в исходном коде.
Предполагается заменить этой функцией шестнадцатеричные строки литералов, начинающиеся с
'x', которые могут быть удалены для упрощения основного языка.
Параметры: hexData |
преобразуемая строка. |
Возвращает: string, wstring или dstring, в соответсвии с типом hexData.
Примеры: auto string1 = hexString!"304A314B";
assert(string1 == "0J1K");
auto string2 = hexString!"304A314B"w;
assert(string2 == "0J1K"w);
auto string3 = hexString!"304A314B"d;
assert(string3 == "0J1K"d);
pure nothrow @nogc @safe auto
toChars
(ubyte radix = 10, Char = char, LetterCase letterCase = LetterCase.lower, T)(T
value
)
if
((radix == 2 || radix == 8 || radix == 10 || radix == 16) &&
(is(Unqual!T == uint) || is(Unqual!T == ulong) || radix == 10 &&
(is(Unqual!T == int) || is(Unqual!T == long))));
Преобразование целого в диапазон символов. Предназначен быть легким и быстрым.
Параметры: radix |
2, 8, 10, 16 |
Char |
тип символов для вывода |
letterCase |
lower (нижний) для deadbeef, upper (верхний) для DEADBEEF |
T value |
преобразуемое целое. Может быть uint или ulong. Если основание равно 10, может также быть int или long. |
Возвращает: Диапазон с произвольным доступом с поддержкой срезов и всего