Question

I'm using a template to convert integral types into a string representation of their binary values. I used the following:

template<typename T>
std::string ToBinary(const T& value)
{
    const std::bitset<std::numeric_limits<T>::digits + 1> bs(value);
    const std::string s(bs.to_string());

    return s;
}

It works for int but doesn't compile with unsigned int :

unsigned int buffer_u[10];
int buffer_i[10];
...
ToBinary(buffer_i[1]); //compile and works
ToBinary(buffer_u[1]); //doesn't compile -- ambiguous overload

Could you explain why?

EDIT:

Yes, I'm using VS2010

Was it helpful?

Solution

Not your ToBinary call is ambiguous, its the constructor call of bitset with an unsigned value. Unfortunately this is a VC++ Bug: http://connect.microsoft.com/VisualStudio/feedback/details/532897/problems-constructing-a-bitset-from-an-unsigned-long-in-the-vc-rc

Edit - Workaround:

template<>
std::string ToBinary<unsigned int>(const unsigned int& value)
{
    const std::bitset<std::numeric_limits<unsigned int>::digits> bs(static_cast<unsigned long long>(value));
    return bs.to_string();
}

OTHER TIPS

If you look at the standard (FDIS n3290), then you see that std::bitset has multiple constructors:

First there is this one:

20.5.1 bitset constructors [bitset.cons]

constexpr bitset(unsigned long long val) noexcept;

Effects: Constructs an object of class bitset, initializing the first M bit positions to the corresponding bit values in val. M is the smaller of N and the number of bits in the value representation (3.9) of unsigned long long. If M < N, the remaining bit positions are initialized to zero.

Then there is also this one, which I suspect might be might cause things to become ambigious, when you call it with unsigned int

template <class charT>
explicit bitset(
const charT* str,
typename basic_string<charT>::size_type n = basic_string<charT>::npos,
charT zero = charT(’0’), charT one = charT(’1’));

Effects: Constructs an object of class bitset as if by

bitset( n == basic_string<charT>::npos ? basic_string<charT>(str) :
basic_string<charT>(str, n), 0, n, zero, one)

Are you using VC10? There is already an issue reported: Microsoft connect. Also I'd guess that you might be able to fix it by casting the type to int if it is 32 bit, like this:

string s = ToBinary(*reinterpret_cast<int*>(&buffer_u[1]));

This can be done inside of the method as well if needed. The result of the reinterpret should not be used for arithmetics anymore, though. ;)

Works fine as workaround for me (but looks quite ugly)

template<typename T>
std::string ToBinary(const T& value)
{
    switch (sizeof(T))
    {
    case 8:
        return std::bitset<std::numeric_limits<T>::digits + 1>(*reinterpret_cast<const long*>(&value)).to_string();
    case 4:
        return std::bitset<std::numeric_limits<T>::digits + 1>(*reinterpret_cast<const int*>(&value)).to_string();
    case 2:
        return std::bitset<std::numeric_limits<T>::digits + 1>(*reinterpret_cast<const short*>(&value)).to_string();
    case 1:
        return std::bitset<std::numeric_limits<T>::digits + 1>(*reinterpret_cast<const char*>(&value)).to_string();
    }
    return "n/a";
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top