I'm writing my own little utility library, and I've opted to do something which I don't really see often (and there might be a reason) - I'm trying to implement a 'perfect' wrapper around C++ integer classes (think int, long long, etc.). I've managed to do this, and it works just fine, but I keep getting warnings from static cast invocations (C4244).
My implementation:
This is my implementation for a 'replacement' for the int type, other types are implemented in the same way, but, for the sake of brevity, I'll just share the int one. (in my source code, I've implemented this using macros).
struct i32 {
constexpr i32() = default;
constexpr i32(int32_t v) : value(v) {}
constexpr i32(const i32& b) = default;
constexpr i32(i32&& b) noexcept : value(std::exchange(b.value, 0)) {}
~i32() = default;
constexpr auto operator=(const i32& b) -> i32& {
if(this != &b) {
value = b.value;
}
return *this;
}
constexpr auto operator=(i32&& b) noexcept -> i32& {
if(this != &b) {
value = std::exchange(b.value, 0);
}
return *this;
}
constexpr auto operator+=(int32_t x) -> i32& {
value += x;
return *this;
}
constexpr auto operator-=(int32_t x) -> i32& {
value -= x;
return *this;
}
constexpr auto operator*=(int32_t x) -> i32& {
value *= x;
return *this;
}
constexpr auto operator%=(int32_t x) -> i32& {
value %= x;
return *this;
}
constexpr auto operator&=(int32_t x) -> i32& {
value &= x;
return *this;
}
constexpr auto operator|=(int32_t x) -> i32& {
value |= x;
return *this;
}
constexpr auto operator^=(int32_t x) -> i32& {
value ^= x;
return *this;
}
constexpr auto operator<<=(int32_t x) -> i32& {
value <<= x;
return *this;
}
constexpr auto operator>>=(int32_t x) -> i32& {
value >>= x;
return *this;
}
constexpr auto operator/=(int32_t x) -> i32& {
value /= x;
return *this;
}
constexpr auto operator++() -> i32& {
++value;
return *this;
}
constexpr auto operator++(int) -> i32 {
i32 tmp(*this);
++(*this);
return tmp;
}
constexpr auto operator--() -> i32& {
--value;
return *this;
}
constexpr auto operator--(int) -> i32 {
i32 tmp(*this);
--(*this);
return tmp;
}
constexpr auto operator~() const -> i32 {
return i32(~value);
}
constexpr operator int32_t() const {
return value;
}
int32_t value;
};
Simple test case
u64 a = 10; // u64 is a uint64_t replacement
i32 b = static_cast<i32>(a); // argument: conversion from uint64_t to int32_t, possible loss of data.
std::cout << a << '\n'; // works as expected, outputs '10'
How can I fix this and prevent the warning from appearing (note: I'm not looking for a band aid solution, but a real fix).
I'm using MSVC with C++20
Why?
I've opted to reimplement a section of the standard library, both for the purposes of learning, and to get rid of the compilation overhead. I've thought it would be nice to be able to, instead of using std::numeric_limits<x>::max()
/ whatever, do something like i32::max()
, and it kind of devolved from there.
uint64_t
to aint321_t
without losing data unless the value of theuint64_t
is in the range of theint32_t
.u64
? I don't understand what auint64_t
replacement is. Is it yet another class likei32
?uint64_t
toint32_t
, you'll get this warning, too. So your replacement works exactly like the real deal. Is this not what you want?