#include <iostream>
#include <bitset>
using namespace std;
typedef unsigned short uint16_t;
typedef short int16_t;
#define CHAR_BIT 8

template <typename T,size_t count> static T convertBitSetToNumber( const std::bitset<count>& bitset )
{
    T result;
    #define targetSize (sizeof( T )*CHAR_BIT)
    if ( targetSize > count )
    {
        // if bitset is 0xF00, converting it as 0x0F00 will lose sign information (0xF00 is negative, while 0x0F00 is positive)
        // This is because sign bit is on the left.
        // then, we need to add a zero (4bits) on the right and then convert 0xF000, later, we will divide by 16 (2^4) to preserve sign and value

        size_t missingbits = targetSize - count;

        std::bitset<targetSize> extended;
        extended.reset(); // set all to 0
        for ( size_t i = 0; i != count; ++i )
        {
            if ( i < count )
                extended[i+missingbits] = bitset[i];
        }

        result = static_cast<T>( extended.to_ullong() );
		
		int mask = 1 << (targetSize-missingbits-1);
		mask |= mask - 1;
		
        result = result >> missingbits;
        result = result & mask;

        return result;
    }
    else
    {
        return static_cast<T>( bitset.to_ullong() );
    }
}

int main() {
uint16_t val1 = convertBitSetToNumber<uint16_t,12>( std::bitset<12>( "100010011010" ) );
// val1 is 0x089A
int16_t val2 = convertBitSetToNumber<int16_t,12>( std::bitset<12>( "100010011010" ) );

	cout << std::hex << val1 << endl;
	cout << std::hex << val2 << endl;
	return 0;
}