Bitwise Integer Conversion
<p>I have to use an API that returns int32_t. But the actual value might be of a smaller signed/unsigned type. To Know the the exact type the API returns ENUM values. It looks something like this:</p>

<pre><code>typedef enum Int{
    Int8,
    Int16,
    Int32,
    Uint8,
    Uint16,
    Uint32
}IntT;

typedef struct{
    IntT (*getType)();
    void (*getInt)(int32_t* out);

}IntegerT;
</code></pre>

<p>I want to convert the value from int32_t to the actual type by knowing the enum value. Sometimes I even want to assign for example an unsigned int32 to an unsigned int64 variable in my code. Knowing that the unsigned int32 is returned as int32_t if the value is big enough then it is represented as a negative value in in this type and if I just static_cast it to uint64_t then the sign bit is extended to fill all the the higher bits in uint64_t which yields a totally different unsigned value than that is intended.</p>

<p>Therefore, I have written a cast function that should take care of casting to a bigger int type or a smaller int type to the correct value. However, I feel that this might be a known issue and there might be an already existing solution. Below is the function. Please inform if you think this can be improved or if there is a better solution (I have made this function a bit more generic than I really need for my usecase though).</p>

<p>EDIT: Made this portable with regards to Endianness.</p>

<p>EDIT: Removed compiler warnings about signed/unsigned comparisons.</p>

<pre><code>#include &lt;limits&gt;
#include &lt;boost/static_assert.hpp&gt; //BOOST_STATIC_ASSERT
#include &lt;stdexcept&gt;
#include &lt;cstring&gt;
#include &lt;boost/type_traits/make_unsigned.hpp&gt;


namespace Detail
{
/** This a implementation helper class for bitwise_int_cast function */
template&lt;bool IsToTypeSigned, bool IsFromTypeSigned&gt;
class Converter
{
public:
    template&lt;typename ToIntType, typename FromIntType&gt;
    ToIntType convert(FromIntType from) {
        BOOST_STATIC_ASSERT(sizeof(from) == 0); //This prevents this generic implementation being compiled
        return from;
    }
};

/** From signed to signed */
template&lt;&gt;
template&lt;typename ToIntType, typename FromIntType&gt;
ToIntType Converter&lt;true, true&gt;::convert(FromIntType from)
{
    BOOST_STATIC_ASSERT(std::numeric_limits&lt;ToIntType&gt;::is_signed &amp;&amp; std::numeric_limits&lt;FromIntType&gt;::is_signed);
    if((from &lt; std::numeric_limits&lt;ToIntType&gt;::min()) ||
            (from &gt; std::numeric_limits&lt;ToIntType&gt;::max())
      ) {
        throw std::runtime_error("Integer overflow in casting from large signed rvalue into smaller signed lvalue");
    }
    return static_cast&lt;ToIntType&gt;(from);
}

/** From signed to unsigned */
template&lt;&gt;
template&lt;typename ToIntType, typename FromIntType&gt;
ToIntType Converter&lt;false, true&gt;::convert(FromIntType from)
{
    BOOST_STATIC_ASSERT(!std::numeric_limits&lt;ToIntType&gt;::is_signed &amp;&amp; std::numeric_limits&lt;FromIntType&gt;::is_signed);
   typedef typename boost::make_unsigned&lt;FromIntType&gt;::type unsignedType;
   unsignedType unsignedIn = from;

   if(std::numeric_limits&lt;FromIntType&gt;::digits &lt; std::numeric_limits&lt;ToIntType&gt;::digits) {
       if(from &lt; 0) {
           return unsignedIn;
       }
    } else {
        if(from &gt; 0) {
            if (unsignedIn &gt; std::numeric_limits&lt;ToIntType&gt;::max()) {
                throw std::runtime_error("Integer overflow in casting from large signed rvalue into smaller unsigned lvalue");
            }
        } else if (from &lt; 0) {
            throw std::runtime_error("Integer overflow in casting from large signed rvalue into smaller unsigned lvalue");
        }
    }
    return unsignedIn;
}

/** From unsigned to signed */
template&lt;&gt;
template&lt;typename ToIntType, typename FromIntType&gt;
ToIntType Converter&lt;true, false&gt;::convert(FromIntType from)
{
    BOOST_STATIC_ASSERT(std::numeric_limits&lt;ToIntType&gt;::is_signed &amp;&amp; !std::numeric_limits&lt;FromIntType&gt;::is_signed);
    if(std::numeric_limits&lt;ToIntType&gt;::digits &lt; std::numeric_limits&lt;FromIntType&gt;::digits) {
        typename boost::make_unsigned&lt;ToIntType&gt;::type allBitsSet = -1; //e.g. 0xFFFF
        if( from &gt; allBitsSet) {
            throw std::runtime_error("Integer overflow in casting from large unsigned rvalue into smaller signed lvalue");
        }
    }
    return static_cast&lt;ToIntType&gt;(from);
}

/** From unsigned to unsigned */
template&lt;&gt;
template&lt;typename ToIntType, typename FromIntType&gt;
ToIntType Converter&lt;false, false&gt;::convert(FromIntType from)
{

    if(from &gt; std::numeric_limits&lt;ToIntType&gt;::max()) {
        throw std::runtime_error("Integer overflow in casting from large unsigned rvalue into smaller unsigned lvalue");
    }
    return static_cast&lt;ToIntType&gt;(from);
}


}


/**
 * This cast only cares about integer sizes not sign mismatch
 * works only on two's complement (Big or Little Endian) Machines
 */
template&lt;typename ToIntType, typename FromIntType&gt;
inline ToIntType bitwise_int_cast(FromIntType from)
{
    BOOST_STATIC_ASSERT(std::numeric_limits&lt;ToIntType&gt;::is_integer &amp;&amp; std::numeric_limits&lt;FromIntType&gt;::is_integer);
    Detail::Converter&lt;std::numeric_limits&lt;ToIntType&gt;::is_signed, std::numeric_limits&lt;FromIntType&gt;::is_signed&gt; converter;
    return converter.template convert&lt;ToIntType&gt;(from);
}
</code></pre>
