std::bitset to any integral conversion

631 views
Skip to first unread message

Roman Orlov

unread,
Mar 4, 2017, 6:24:41 AM3/4/17
to ISO C++ Standard - Future Proposals
Here is the typical usage of std::bitset class.
When std::bitset is declared the number of bits is well known.

std::bitset<16> flags;

When fixed-sized integer is declared the number of bits is well known too.

uint16_t flags_register;

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.
Reply all
Reply to author
Forward
0 new messages