www.digitalmars.com

D Programming Language 2.0

Last update Wed Jul 9 01:24:37 2008

std.conv

A one-stop shop for converting values from one type to another.

Authors:
Walter Bright, Andrei Alexandrescu

class ConvError: object.Error;
Thrown on conversion errors.

class ConvOverflowError: object.Error;
Thrown on conversion overflow errors.

template to(Target)
The to family of functions converts a value from type Source to type Target. The source type is deduced and the target type must be specified, for example the expression to!(int)(42.0) converts the number 42 from double to int. The conversion is "safe", i.e., it checks for overflow; to!(int)(4.2e10) would throw the ConvOverflowError exception. Overflow checks are only inserted when necessary, e.g., to!(double)(42) does not do any checking because any int fits in a double.

Converting a value to its own type (useful mostly for generic code) simply returns its argument.

Example:
int a = 42;
auto b = to!(int)(a); // b is int with value 42
auto c = to!(double)(3.14); // c is double with value 3.14
Converting among numeric types is a safe way to cast them around. Conversions from floating-point types to integral types allow loss of precision (the fractional part of a floating-point number). The conversion is truncating towards zero, the same way a cast would truncate. (To round a floating point value when casting to an integral, use roundTo.)

Examples:
int a = 420;
auto b = to!(long)(a); // same as long b = a;
auto c = to!(byte)(a / 10); // fine, c = 42
auto d = to!(byte)(a); // throw ConvOverflowError
double e = 4.2e6;
auto f = to!(int)(e); // f == 4200000
e = -3.14;
auto g = to!(uint)(e); // fails: floating-to-integral underflow
e = 3.14;
auto h = to!(uint)(e); // h = 3
e = 3.99;
h = to!(uint)(a); // h = 3
e = -3.99;
f = to!(int)(a); // f = -3
Conversions from integral types to floating-point types always succeed, but might lose accuracy. The largest integers with a predecessor representable in floating-point format are 2^24-1 for float, 2^53-1 for double, and 2^64-1 for real (when real is 80-bit, e.g. on Intel machines).

Example:
int a = 16_777_215; // 2^24 - 1, largest proper integer representable as float
assert(to!(int)(to!(float)(a)) == a);
assert(to!(int)(to!(float)(-a)) == -a);
a += 2;
assert(to!(int)(to!(float)(a)) == a); // fails!
Conversions from string to numeric types differ from the C equivalents atoi() and atol() by checking for overflow and not allowing whitespace.

For conversion of strings to signed types, the grammar recognized is:
Integer: Sign UnsignedInteger
UnsignedInteger
Sign:
    +
    -
For conversion to unsigned types, the grammar recognized is:
UnsignedInteger:
    DecimalDigit
    DecimalDigit UnsignedInteger


Converting an array to another array type works by converting each element in turn. Associative arrays can be converted to associative arrays as long as keys and values can in turn be converted.

Example:
int[] a = ([1, 2, 3]).dup;
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);
Conversions operate transitively, meaning that they work on arrays and associative arrays of any complexity:

int[string][double[int[]]] a;
...
auto b = to!(short[wstring][string[double[]]])(a);
This conversion works because to!(short) applies to an int, to!(wstring) applies to a string, to!(string) applies to a double, and to!(double[]) applies to an int[]. The conversion might throw an exception because to!(short) might fail the range check.

template roundTo(Target)
Rounded conversion from floating point to integral.

Example:
  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);
Rounded conversions do not work with non-integral target types.

template parse(Target)
The parse family of functions works quite like the to family, except that (1) it only works with strings as input, (2) takes the input string by reference and advances it to the position following the conversion, and (3) does not throw if it could not convert the entire string. It still throws if an overflow occurred during conversion or if no character of the input string was meaningfully converted.

Example:
string test = "123 \t  76.14";
auto a = parse!(uint)(test);
assert(a == 123);
assert(test == " \t  76.14"); // parse bumps string
munch(test, " \t\n\r"); // skip ws
assert(test == "76.14");
auto b = parse!(double)(test);
assert(b == 76.14);
assert(test == "");


int toInt(string s);
uint toUint(string s);
long toLong(string s);
ulong toUlong(string s);
short toShort(string s);
ushort toUshort(string s);
byte toByte(string s);
ubyte toUbyte(string s);
float toFloat(Char)(Char[] s);
double toDouble(Char)(Char[] s);
real toReal(Char)(Char[] s);
Convert character string to the return type. These functions will be deprecated because to!(T) supersedes them.