Here is the typical usage of std::bitset class.
When std::bitset is declared the number of bits is well known.
When fixed-sized integer is declared the number of bits is well known too.
When we try to convert flags to flags_register we have a problem
flags_register = flags.to_ulong();
to_ulong() returns an unsigned long number. The size of unsigned long may be 4 or 8 bytes depending on platform. But we need neither 4 nor 8 bytes, only 2 bytes.
Moreover to_ulong() can throw an exception. It is known there will be no exceptions in the case of 16 bits.
But the code works.
One day we decided to compile our project with the option -Wconversion. And there will be a warning message like this
Warning: conversion to ‘uint16_t {aka short unsigned int}’ from ‘long unsigned int’ may alter its value [-Wconversion]
flags_register = flags.to_ulong();
~~~~~~~~~~~~~~^~
To suppress that warning we have to use explicit narrowing cast
flags_register = static_cast<uint16_t>(flags.to_ulong());
To solve this problem I suggest the new method for std::bitset class
#include <type_traits>
template<std::size_t N>
class bitset
{
// ...
template<typename T>
T as_integral() const noexcept
{
static_assert(std::is_integral<T>::value && N <= sizeof(T) * 8);
//...
}
// ...
};
Also it makes converting bitset to smaller integer impossible at compile time. That saves us from losing bits during careless convertions.
std::bitset<16> bs;
bs.as_integral<uint16_t>();
bs.as_integral<uint8_t>(); // COMPILATION ERROR HERE!
That's the idea.