0

I have something like this:

template<class T>
class SomeClass {
public:
    typedef std::make_unsigned<T> unsigned_t;
    unsigned_t maxBinBitRep_ { - 1 };    
};

int main() {
    // Okay prints out 255 as expected.
    SomeClass<unsigned char>  unsignedChar;  // unsigned version
    // New to `make_unsigned<>` but should print 255.
    //std::cout << unsignedChar.maxBinBitRep << std::endl; 

    // Should be printing the same as above however it's printing: 4294967295
    SomeClass<char> signedChar;
    // same as above.
    //std::cout << signedChar.maxBinBitRep << std::endl; // signed version


    std::cout << "/nPress any key and enter to quit./n" );
    char q;
    std::cin >> q;

    return 0;
}

I'm trying to take the integral type that is passed into the template's parameter list and make a unsigned version of it and initializing it to -1. This should give me the value that I need for any integral type.

Am I using std::make_unsigned correctly?

my mistake miss the keyword class in the declaration... fixed typo.


EDIT - My Actual Class:

template<class T>
class showBinary {
public:
    static const std::size_t standardByteWidth_ { 8 };  
private:
    typedef std::make_unsigned<T> unsigned_t;
    unsigned_t maxVal_ { -1 };

    T t_;
    std::vector<unsigned> bitPattern_;
    std::size_t size_ = sizeof( T );        

public:
    explicit showBinary( T t ) : t_( t ) {

        bitPattern_.resize( size_ * standardByteWidth_ );
        for ( int i = ((maxVal_ + 1) / 2); i >= 1; i >>= 1 ) {
            if ( t_ & i ) {
                bitPattern_.emplace_back( 1 );
            } else {
                bitPattern_.emplace_back( 0 );
            }
        }
    }    

    template<typename U>
    friend std::ostream& operator<<( std::ostream& out, const showBinary<U>& val ) {
        std::ostringstream ostring;
        ostring << "Val: " << val.t_ << " ";
        ostring << "Max Value: " << val.maxVal_ << "\n";
        ostring << "Size in bytes: " << val.size_ << " ";
        ostring << "Number of bits: " << val.size_ * val.standardByteWidth_ << "\n";

        ostring << "Bit Pattern: ";

        for ( auto t : val.bitPattern_ ) {
            ostring << t;
        }
        ostring << std::endl;

        out << ostring.str();
        return out;
    }

};

Its use:

int main() {
    showBinary<unsigned char> ucBin( 5 );
    showBinary<char> scBin( 5 );
    std::cout << ucBin << std::endl;
    std::cout << scBin << std::endl;

    std::cout << "\nPress any key and enter to quit." << std::endl;
    char q;
    std::cin >> q;

    return 0;        
}
Francis Cugler
  • 7,788
  • 2
  • 28
  • 59
  • 1
    [Cannot reproduce](http://coliru.stacked-crooked.com/a/5e820a37e4394b37), after I've fixed all the compilation errors in your code. Can you provide the *exact* version which fails for you? – Angew is no longer proud of SO Dec 29 '17 at 13:55
  • Is there a reason to not use `std::numeric_limits`? Then the whole thing can be banished into abyss. – Incomputable Dec 29 '17 at 13:59
  • @Incomputable could u show me an example? I just read through `make_unsigned` to learn it; I'd have to go back and read through `numeric_limits` too. – Francis Cugler Dec 29 '17 at 14:02
  • 1
    `std::numeric_limits>::max()` should give you the maximum possible value for the type. – Incomputable Dec 29 '17 at 14:03
  • @Angew I updated my question and fixed the typo. – Francis Cugler Dec 29 '17 at 14:22
  • `unsigned_t maxVal_ { -1 };` is probably not what you want, depending on how portable you want it to be. You should either use Incomputable's suggestion, or use `unsigned_t maxVal_ { ~unsigned_t{0} };`. – Eljay Dec 29 '17 at 14:25

2 Answers2

5

Am I using std::make_unsigned correctly?

Not quite. Fix:

typedef typename std::make_unsigned<T>::type unsigned_t;

You can convert a value of any integer type to its binary string representation by using std::bitset<>::to_string function:

template<class T>
std::string as_binary_string(T value) {
    return std::bitset<sizeof(T) * 8>(value).to_string();
}
Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271
  • Your suggestion of `typedef typename std::make_unsigned::type unsigned_t` worked. I had previously tried with `::type` appended to the end but it would fail. I think that's why I moved away from the `::type` at the end. I was also missing the `typename` after the `typedef`. I could use the little function you supplied, however, I will be expanding this class to do other types as well mainly, `floating point` types. If all goes well I might even try to do simple class & structs as long as they are not inherited, polymorphic, abstract and don't contain any virtual or static methods... – Francis Cugler Dec 30 '17 at 03:42
  • ... the class or structs might be a real challenge if even possible at all. I'll accept your answer because it led me towards getting the right functionality for `integral types`. – Francis Cugler Dec 30 '17 at 03:43
  • 1
    To be on the super-safe side, you'd replace the `8` with `CHAR_BIT`. – Angew is no longer proud of SO Dec 30 '17 at 10:41
0

Buggy loop

I don't even know what you want to achieve with that loop, but it certainly will not do what you want. Also you're mixing signed and unsigned types in your loop, so it is completely wrong.


You seem to want to print a binary representation of the unsigned type. There is a very old post by Jerry.


Your code:

I believe that you should either store std::string directly, or std::bitset. To fill the former, just use this:

for (std::size_t i = 0; i < sizeof(UnsignedIntegral) * CHAR_BIT; ++i)
{
    bview += (value % 2) '1' : '0';
    value /= 2;
}

std::reverse(bview.begin(), bview.end());

demo.


Overall your logic seems convoluted, and you believe that compiler will not be able to optimize division by power of two into bitshift. If you're not on overly exotic system, compiler will always optimize this, and much more.

Incomputable
  • 2,188
  • 1
  • 20
  • 40
  • Close; I want to do a binary representation of "ANY" type; for right now I'm concentrated on the `integral types`. The template class should work on both signed and unsigned versions. But I need the value of max bit representation to get the binary digits and to get that if the type is `signed` I need `unsigned type(-1)` instead of `signed type (-1)` – Francis Cugler Dec 29 '17 at 14:38
  • @FrancisCugler, just use `value % 2`. This is not the best case to use bit fiddling. – Incomputable Dec 29 '17 at 14:39
  • For right now It's just a class to "display" binary information about a type and the value passed into its constructor. – Francis Cugler Dec 29 '17 at 14:40