I've been trying to make signed literal short hands for <cstdint>
types, for example, u8, u16, etc...
I developed a function like this:
constexpr std::int8_t operator "" _i8(unsigned long long int value){
unsigned long long int mask = 0xEF;
if(value && mask == value){
return static_cast<std::int8_t>(value);
}else{
throw std::out_of_range("");
}
}
I then looked up and found that -
is actually not part of the literal. What this means for me is that the above code( if it included 128, right now it doesn't) wouldn't actually work correctly for -128.
When I try this out in godbolt
#include <type_traits>
#include <iostream>
#include <cstdint>
#include <bitset>
int main(){
std::cout << std::bitset<8>(static_cast<std::int8_t>(128)) << std::endl;
std::cout << static_cast<std::int32_t>(static_cast<std::int8_t>(128)) << std::endl;
std::cout << static_cast<std::int32_t>(static_cast<std::int8_t>(-128)) << std::endl;
std::cout << static_cast<std::int32_t>(-static_cast<std::int8_t>(128)) << std::endl;
return 0;
}
I get 10000000
, -128
, -128
, and 128
Technically using 128 could work in the above example, it would just force the value to be -128 on the output, but when they (correctly) add a negative, it will turn into 128, and not be a int8_t. I'd like errors on 128 with no negative, and no errors on 128 with negative.
I thought about making some sort of temporary object with -
overloaded for it, and implicitly converting, but even with that, it won't work properly in template functions, so the unary - operator would have to return the base type, and I would somehow have to return the base type switched on if the value is 128 or not, but I don't think that's possible.
I basically want the following to work:
template<typename T>
foo(const T& bar, const T& baz);
foo(127_i8, std::int8_t(32));
foo(-128_i8, std::int8_t(32));
and this to not work:
foo(128_i8, std::int8_t(32));