...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
All of the number types that are based on number
have certain conversion rules in common. In particular:
cpp_dec_float_50 df(0.5); // OK construction from double cpp_int i(450); // OK constructs from signed int cpp_int j = 3.14; // Error, lossy conversion.
cpp_int i(3.14); // OK explicit conversion i = static_cast<cpp_int>(3.14) // OK explicit conversion i.assign(3.14); // OK, explicit assign and avoid a temporary from the cast above i = 3.14; // Error, no implicit assignment operator for lossy conversion. cpp_int j = 3.14; // Error, no implicit constructor for lossy conversion.
number
can be converted
to any built in type, via the convert_to
member function:
mpz_int z(2); int i = z.template convert_to<int>(); // sets i to 2
Additional conversions may be supported by particular backends.
number
can be converted
to any built in type, via an explicit conversion operator: this functionality
is only available on compilers supporting C++11's explicit conversion
syntax.
mpz_int z(2); int i = z; // Error, implicit conversion not allowed. int j = static_cast<int>(z); // OK explicit conversion.
const char*
or a std::string
:
// pi to 50 places from a string: cpp_dec_float_50 df("3.14159265358979323846264338327950288419716939937510"); // Integer type will automatically detect "0x" and "0" prefixes and parse the string accordingly: cpp_int i("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000"); // Invalid input always results in a std::runtime_error being thrown: i = static_cast<cpp_int>("3.14"); // implicit conversions from strings are not allowed: i = "23"; // Error, no assignment operator for implicit conversion from string // assign member function, avoids having to create a temporary via a static_cast: i.assign("23"); // OK
// pi to 50 places from a string: cpp_dec_float_50 df = "3.14159265358979323846264338327950288419716939937510"; // Multiply by 2 - using an integer literal here is usually more efficient // than constructing a temporary: df *= 2; // You can't mix integer types with floats though: cpp_int i = 2; i *= 3.14; // Error, no *= operator will be found.
cpp_dec_float_50 df = "3.14159265358979323846264338327950288419716939937510"; // Now print at full precision: std::cout << std::setprecision(std::numeric_limits<cpp_dec_float_50>::max_digits10) << df << std::endl cpp_int i = 1; i <<= 256; // Now print in hex format with prefix: std::cout << std::hex << std::showbase << i << std::endl;
int128_t i128 = 0; int266_t i256 = i128; // OK implicit widening conversion i128_t = i256; // Error, no assignment operator found, narrowing conversion is explicit i128_t = static_cast<int128_t>(i256); // OK, explicit narrowing conversion mpz_int z = 0; mpf_float f = z; // OK, GMP handles this conversion natively, and it's not lossy and therefore implicit mpf_float_50 f50 = 2; f = f50; // OK, conversion from fixed to variable precision, f will have 50 digits precision. f50 = f; // Error, conversion from variable to fixed precision is potentially lossy, explicit cast required.
cpp_int cppi(2); // We can always convert between numbers of the same category - // int to int, rational to rational, or float to float, so this is OK // as long as we use an explicit conversion: mpz_int z(cppi); // We can always promote from int to rational, int to float, or rational to float: cpp_rational cppr(cppi); // OK, int to rational cpp_dec_float_50 df(cppi); // OK, int to float df = static_cast<cpp_dec_float_50>(cppr); // OK, explicit rational to float conversion // However narrowing and/or implicit conversions always fail: cppi = df; // Compiler error, conversion not allowed
mpf_t m; // Native GMP type. mpf_init_set_ui(m, 0); // set to a value; mpf_float i(m); // copies the value of the native type.
More information on what additional types a backend supports conversions from are given in the tutorial for each backend. The converting constructor will be implicit if the backend's converting constructor is also implicit, and explicit if the backends converting constructor is also explicit.