#include #include #include #define try_convert(exp_pass, fn, i) \ try_convert_real(#fn "(" #i ")", exp_pass, fn, i) template static void try_convert_real( char const* description, bool exp_pass, To (*fn)(From const&), From const& i) { bool passed = false; try { To result = fn(i); passed = true; std::cout << description << ": " << i << " " << result; } catch (std::range_error& e) { std::cout << description << ": " << e.what(); passed = false; } std::cout << ((passed == exp_pass) ? " PASSED" : " FAILED") << std::endl; } #define try_range_check(exp_pass, a, b) \ try_range_check_real(#a " + " #b, exp_pass, a, b) template static void try_range_check_real( char const* description, bool exp_pass, T const& a, T const& b) { bool passed = false; try { QIntC::range_check(a, b); std::cout << description << ": okay"; passed = true; } catch (std::range_error& e) { std::cout << description << ": " << e.what(); passed = false; } std::cout << ((passed == exp_pass) ? " PASSED" : " FAILED") << std::endl; } #define try_range_check_subtract(exp_pass, a, b) \ try_range_check_subtract_real(#a " - " #b, exp_pass, a, b) template static void try_range_check_subtract_real( char const* description, bool exp_pass, T const& a, T const& b) { bool passed = false; try { QIntC::range_check_substract(a, b); std::cout << description << ": okay"; passed = true; } catch (std::range_error& e) { std::cout << description << ": " << e.what(); passed = false; } std::cout << ((passed == exp_pass) ? " PASSED" : " FAILED") << std::endl; } int main() { uint32_t u1 = 3141592653U; // Too big for signed type int32_t i1 = -1153374643; // Same bit pattern as u1 uint64_t ul1 = 1099511627776LL; // Too big for 32-bit uint64_t ul2 = 12345; // Fits into 32-bit int32_t i2 = 81; // Fits in char and uchar signed char c1 = static_cast('\xf7'); // Signed value when char char c2 = 'W'; // char; may be signed or unsigned // Verify i1 and u1 have same bit pattern assert(static_cast(i1) == u1); // Verify that we can unsafely convert between signed and unsigned char assert(c1 == static_cast(static_cast(c1))); try_convert(true, QIntC::to_int, i1); try_convert(true, QIntC::to_uint, u1); try_convert(false, QIntC::to_int, u1); try_convert(false, QIntC::to_uint, i1); try_convert(false, QIntC::to_int, ul1); try_convert(true, QIntC::to_int, ul2); try_convert(true, QIntC::to_uint, ul2); try_convert(true, QIntC::to_offset, u1); try_convert(true, QIntC::to_offset, i1); try_convert(false, QIntC::to_ulonglong, i1); try_convert(true, QIntC::to_char, i2); try_convert(true, QIntC::to_uchar, i2); try_convert(false, QIntC::to_uchar, c1); try_convert(true, QIntC::to_uchar, c2); try_convert(true, QIntC::to_char, c2); auto constexpr max_ll = std::numeric_limits::max(); auto constexpr max_ull = std::numeric_limits::max(); auto constexpr min_ll = std::numeric_limits::min(); auto constexpr max_sc = std::numeric_limits::max(); try_range_check(true, 1, 2); try_range_check(true, -1, 2); try_range_check(true, -100, -200); try_range_check(true, max_ll, 0LL); try_range_check(false, max_ll, 1LL); try_range_check(true, max_ll, 0LL); try_range_check(false, max_ll, 1LL); try_range_check(true, max_ull, 0ULL); try_range_check(false, max_ull, 1ULL); try_range_check(true, min_ll, 0LL); try_range_check(false, min_ll, -1LL); try_range_check(false, max_sc, max_sc); try_range_check(true, '!', '#'); try_range_check_subtract(true, 1, 2); try_range_check_subtract(true, -1, -2); try_range_check_subtract(true, 1, 10); try_range_check_subtract(true, -1, -10); try_range_check_subtract(false, 0LL, min_ll); try_range_check_subtract(false, 1LL, min_ll); try_range_check_subtract(true, 0LL, max_ll); try_range_check_subtract(true, -1LL, max_ll); try_range_check_subtract(false, -2LL, max_ll); return 0; }