#include <iostream>
#include <limits>
using namespace std;
template<typename Desired, typename Given>
constexpr Desired narrow_cast(Given arg) {
static_assert(std::is_integral<Desired>::value, "Only integer types are supported");
static_assert(std::is_integral<Given>::value, "Only integer types are supported");
auto min = std::numeric_limits<Desired>::min();
auto max = std::numeric_limits<Desired>::max();
auto different_signs = std::is_signed<Given>::value xor std::is_signed<Desired>::value;
if(sizeof(Desired) == sizeof(Given) && different_signs && arg < 0) {
return 0;
}
return
min > arg? min:
max < arg? max:
arg;
}
#define EXPECT_EQ(x, y) if (x != y) cout << "Failed test for " << #x \
<< "\nexpected: " << y \
<< "\n actual: " << x << endl; else
int main() {
// to smaller type signed to signed
EXPECT_EQ(narrow_cast<short>(100000), 32767);
EXPECT_EQ(narrow_cast<short>(-100000), -32768);
EXPECT_EQ(narrow_cast<short>(0), 0);
EXPECT_EQ(narrow_cast<short>(-1), -1);
// to smaller type unsigned to unsigned
EXPECT_EQ(narrow_cast<unsigned short>(100000u), 65535u);
EXPECT_EQ(narrow_cast<unsigned short>(60000u), 60000u);
EXPECT_EQ(narrow_cast<unsigned short>(0u), 0u);
EXPECT_EQ(narrow_cast<unsigned short>(1u), 1u);
// to smaller type signed to signed to unsigned
EXPECT_EQ(narrow_cast<unsigned short>(100000), 65535);
EXPECT_EQ(narrow_cast<unsigned short>(-100000), 0);
EXPECT_EQ(narrow_cast<unsigned short>(0), 0);
EXPECT_EQ(narrow_cast<unsigned short>(-1), 0);
// to smaller type unsigned to signed
EXPECT_EQ(narrow_cast<short>(100000u), 32767);
EXPECT_EQ(narrow_cast<short>(60000u), 32767);
EXPECT_EQ(narrow_cast<short>(0u), 0);
EXPECT_EQ(narrow_cast<short>(1u), 1);
// to same size type signed to signed ////
EXPECT_EQ(narrow_cast<int>(0x7fffffff), 0x7fffffff);
EXPECT_EQ(narrow_cast<int>(-2147483648), -2147483648);
EXPECT_EQ(narrow_cast<int>(0), 0);
EXPECT_EQ(narrow_cast<int>(-1), -1);
// to same size type unsigned to unsigned
EXPECT_EQ(narrow_cast<unsigned int>(0xffffffffu), 0xffffffffu);
EXPECT_EQ(narrow_cast<unsigned int>(60000u), 60000u);
EXPECT_EQ(narrow_cast<unsigned int>(0u), 0u);
EXPECT_EQ(narrow_cast<unsigned int>(1u), 1u);
// to same size type signed to signed to unsigned
EXPECT_EQ(narrow_cast<unsigned int>(0x7fffffff), 0x7fffffffu);
EXPECT_EQ(narrow_cast<unsigned int>(-2147483648), 0u);
EXPECT_EQ(narrow_cast<unsigned int>(0), 0u);
EXPECT_EQ(narrow_cast<unsigned int>(-1), 0u);
// to same size type unsigned to signed
EXPECT_EQ(narrow_cast<int>(0xffffffffu), 0x7fffffff);
EXPECT_EQ(narrow_cast<int>(0x7fffffffu), 0x7fffffff);
EXPECT_EQ(narrow_cast<int>(0x80000000u), 0x7fffffff);
EXPECT_EQ(narrow_cast<int>(0u), 0);
EXPECT_EQ(narrow_cast<int>(1u), 1);
// to bigger size type signed to signed ////
EXPECT_EQ(narrow_cast<int64_t>(0x7fffffff), 0x7fffffffll);
EXPECT_EQ(narrow_cast<int64_t>(-2147483648), -2147483648ll);
EXPECT_EQ(narrow_cast<int64_t>(0), 0);
EXPECT_EQ(narrow_cast<int64_t>(-1), -1ll);
// to bigger size type unsigned to unsigned
EXPECT_EQ(narrow_cast<uint64_t>(0xffffffffu), 0xffffffffull);
EXPECT_EQ(narrow_cast<uint64_t>(60000u), 60000ull);
EXPECT_EQ(narrow_cast<uint64_t>(0u), 0ull);
EXPECT_EQ(narrow_cast<uint64_t>(1u), 1ull);
// to bigger size type signed to signed to unsigned
EXPECT_EQ(narrow_cast<uint64_t>(0x7fffffff), 0x7fffffffull);
EXPECT_EQ(narrow_cast<uint64_t>(-2147483648), 0ull);
EXPECT_EQ(narrow_cast<uint64_t>(0), 0ull);
EXPECT_EQ(narrow_cast<uint64_t>(-1), 0ull);
// to bigger size type unsigned to signed
EXPECT_EQ(narrow_cast<int64_t>(0xffffffffu), 0xffffffffll);
EXPECT_EQ(narrow_cast<int64_t>(0x7fffffffu), 0x7fffffffll);
EXPECT_EQ(narrow_cast<int64_t>(0x80000000u), 0x80000000ll);
EXPECT_EQ(narrow_cast<int64_t>(0u), 0ll);
EXPECT_EQ(narrow_cast<int64_t>(1u), 1ll);
return 0;
}