Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ casting template parameter to its unsigned version

I'm working on a class template that takes a single parameter T of any type. For now I'm interested in integral types; later on when I expand this class to use floating point types I will then specialize this class.

Within this class I have a member variable that will store the max number of bit representations that can be stored in this type. For example:

Fundamental Types & Sizes: Range of values

  • signed char: 1Byte,8 bits,[-127,127] for one's complement or [128,127] for two's complement
  • unsigned char: 1Byte, 8 bits, [0,255]
  • etc.

I can get the max value easier by using the unsigned version of that type so in my template class (pseudo code here):

template<class T>
binaryRep {
    T t_; // store the value
    std::size_t size_ = sizeof( T ); // size in bytes
    std::size_t maxVal = T( -1 ); // This is where I need T to be it's unsigned version.    
};

If someone is to use this template class as such:

void someFunc() {
    binaryRep<unsigned char> binUC; // This works fine

    binaryRep<char> binSC; // Not giving the needed results.
}

Is there a way within the class's constructor to cast T to unsigned T?

In my constructor I was trying to do something like this:

binaryRep( const T& t ) : t_( static_cast<unsigned T>( t ) ) {
}

However this doesn't compile and didn't think it would either... but something of this nature is what I'm needing here.

[Note:] - The maxValue member in this class represents the total number of viable binary bit combinations this type can store. For example: both char & unsigned char of a standard 8 bit byte has a max number of 256 binary bit combinations.

If you need more information than this please let me know.

like image 477
Francis Cugler Avatar asked Jan 28 '26 18:01

Francis Cugler


1 Answers

As far as I know, there is no STL in C++ to give you an unsigned datatype of the signed version.

However, it isn't hard to write your own to get the unsigned type of the corresponding signed data type.

here is a sample of code I created for you.

template<typename T>
struct remove_signed { };

template<>
struct remove_signed<char> { typedef unsigned char Type; };

template<>
struct remove_signed<signed char> { typedef unsigned char Type; };

template<>
struct remove_signed<signed short int> { typedef unsigned short int Type; };

template<>
struct remove_signed<signed int> { typedef unsigned int Type; };

template<>
struct remove_signed<signed long int> { typedef unsigned long int Type; };

template<>
struct remove_signed<signed long long> { typedef unsigned long long Type; };


template<typename T>
using remove_signed_t = typename remove_signed<T>::Type;


int main(int argc, char** argv)
{
   
    signed int x;
    remove_signed<decltype(x)>::Type y; //y is unsigned int

    signed char k;
    remove_signed<decltype(k)>::Type l; //l is unsigned char

    //or
    remove_signed_t<decltype(k)> g; //g is unsigned char
    
    return 0;
}

Good luck.

Edit: As @HolyBlackCat has mentioned, there is std::make_unsigned which can give you unsigned datatype of the signed type And it is exactly implemented as the code above, so if you want to know how std::make_unsigned works, you can check the code.

like image 141
Ahmed Elbadawy Avatar answered Jan 31 '26 07:01

Ahmed Elbadawy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!