Topic: std::bitset to any integral conversion


Author: Roman Orlov <mr.gordon.freman@gmail.com>
Date: Sat, 4 Mar 2017 03:24:41 -0800 (PST)
Raw View
------=_Part_906_521102795.1488626681611
Content-Type: multipart/alternative;
 boundary="----=_Part_907_1612902579.1488626681611"

------=_Part_907_1612902579.1488626681611
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

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 =3D flags.to_ulong();

to_ulong() returns an unsigned long number. The size of unsigned long may=
=20
be 4 or 8 bytes depending on platform. But we need neither 4 nor 8 bytes,=
=20
only 2 bytes.
Moreover to_ulong() can throw an exception. It is known there will be no=20
exceptions in the case of 16 bits.
But the code works.
One day we decided to compile our project with the option -Wconversion. And=
=20
there will be a warning message like this

Warning: conversion to =E2=80=98uint16_t {aka short unsigned int}=E2=80=99 =
from =E2=80=98long=20
unsigned int=E2=80=99 may alter its value [-Wconversion]
flags_register =3D flags.to_ulong();
                 ~~~~~~~~~~~~~~^~


To suppress that warning we have to use explicit narrowing cast

flags_register =3D 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 <=3D sizeof(T) * 8);
        //...
    }
    // ...
};


Also it makes converting bitset to smaller integer impossible at compile=20
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.

--=20
You received this message because you are subscribed to the Google Groups "=
ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to std-proposals+unsubscribe@isocpp.org.
To post to this group, send email to std-proposals@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp=
..org/d/msgid/std-proposals/45a725a4-ad2e-44b4-9ed8-097de9f6eb03%40isocpp.or=
g.

------=_Part_907_1612902579.1488626681611
Content-Type: text/html; charset=UTF-8
Content-Transfer-Encoding: quoted-printable

<div dir=3D"ltr"><div>Here is the typical usage of std::bitset class.</div>=
<div>When std::bitset is declared the number of bits is well known.</div><d=
iv><br></div><div><div class=3D"prettyprint" style=3D"background-color: rgb=
(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid; bor=
der-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><div cl=
ass=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">std</span><span style=3D"color: #660;" class=3D"styled-by-prettify">:=
:</span><span style=3D"color: #000;" class=3D"styled-by-prettify">bitset</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><s=
pan style=3D"color: #066;" class=3D"styled-by-prettify">16</span><span styl=
e=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> flags</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">;</span></div></code></div><br></div>=
<div>When fixed-sized integer is declared the number of bits is well known =
too.</div><div><br></div><div><div class=3D"prettyprint" style=3D"backgroun=
d-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style=
: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"prettypr=
int"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">uint16_t flags_register</span><span style=3D"color: #660;=
" class=3D"styled-by-prettify">;</span></div></code></div></div><div><br></=
div><div>When we try to convert flags to flags_register we have a problem</=
div><div><br></div><div><div class=3D"prettyprint" style=3D"background-colo=
r: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: soli=
d; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><=
div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-b=
y-prettify">flags_register </span><span style=3D"color: #660;" class=3D"sty=
led-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-=
prettify"> flags</span><span style=3D"color: #660;" class=3D"styled-by-pret=
tify">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">to_=
ulong</span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</=
span></div></code></div></div><div><br></div><div>to_ulong() returns an uns=
igned 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.</div><div>Mor=
eover to_ulong() can throw an exception. It is known there will be no excep=
tions in the case of 16 bits.</div><div>But the code works.</div><div>One d=
ay we decided to compile our project with the option -Wconversion. And ther=
e will be a warning message like this</div><div><br></div><div class=3D"pre=
ttyprint" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(=
187, 187, 187); border-style: solid; border-width: 1px; word-wrap: break-wo=
rd;"><code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=
=3D"color: #606;" class=3D"styled-by-prettify">Warning</span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">:</span><span style=3D"color: #=
000;" class=3D"styled-by-prettify"> conversion to </span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">=E2=80=98</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify">uint16_t </span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">{</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify">aka </span><span style=3D"color: #008;" class=
=3D"styled-by-prettify">short</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-=
prettify">unsigned</span><span style=3D"color: #000;" class=3D"styled-by-pr=
ettify"> </span><span style=3D"color: #008;" class=3D"styled-by-prettify">i=
nt</span><span style=3D"color: #660;" class=3D"styled-by-prettify">}=E2=80=
=99</span><span style=3D"color: #000;" class=3D"styled-by-prettify"> </span=
><span style=3D"color: #008;" class=3D"styled-by-prettify">from</span><span=
 style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=3D=
"color: #660;" class=3D"styled-by-prettify">=E2=80=98</span><span style=3D"=
color: #008;" class=3D"styled-by-prettify">long</span><span style=3D"color:=
 #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #008;" c=
lass=3D"styled-by-prettify">unsigned</span><span style=3D"color: #000;" cla=
ss=3D"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"sty=
led-by-prettify">int</span><span style=3D"color: #660;" class=3D"styled-by-=
prettify">=E2=80=99</span><span style=3D"color: #000;" class=3D"styled-by-p=
rettify"> may alter its value </span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">[-</span><span style=3D"color: #606;" class=3D"styled-b=
y-prettify">Wconversion</span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">]</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"><br>flags_register </span><span style=3D"color: #660;" class=3D"styled-=
by-prettify">=3D</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify"> flags</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">to_ulon=
g</span><span style=3D"color: #660;" class=3D"styled-by-prettify">();</span=
><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0</span><span style=3D"c=
olor: #660;" class=3D"styled-by-prettify">~~~~~~~~~~~~~~^~</span><span styl=
e=3D"color: #000;" class=3D"styled-by-prettify"><br><br></span></div></code=
></div><div><br>To suppress that warning we have to use explicit narrowing =
cast</div><div><br></div><div><div class=3D"prettyprint" style=3D"backgroun=
d-color: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style=
: solid; border-width: 1px; word-wrap: break-word;"><code class=3D"prettypr=
int"><div class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">flags_register </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">=3D</span><span style=3D"color: #000;" class=3D"sty=
led-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-by-pr=
ettify">static_cast</span><span style=3D"color: #080;" class=3D"styled-by-p=
rettify">&lt;uint16_t&gt;</span><span style=3D"color: #660;" class=3D"style=
d-by-prettify">(</span><span style=3D"color: #000;" class=3D"styled-by-pret=
tify">flags</span><span style=3D"color: #660;" class=3D"styled-by-prettify"=
>.</span><span style=3D"color: #000;" class=3D"styled-by-prettify">to_ulong=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">());</span=
></div></code></div><br></div><div>To solve this problem I suggest the new =
method for std::bitset class<br></div><div><br></div><div class=3D"prettypr=
int" style=3D"background-color: rgb(250, 250, 250); border-color: rgb(187, =
187, 187); border-style: solid; border-width: 1px; word-wrap: break-word;">=
<code class=3D"prettyprint"><div class=3D"subprettyprint"><span style=3D"co=
lor: #800;" class=3D"styled-by-prettify">#include</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #080;"=
 class=3D"styled-by-prettify">&lt;type_traits&gt;</span><span style=3D"colo=
r: #000;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #00=
0;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #008;" cl=
ass=3D"styled-by-prettify">template</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">&lt;</span><span style=3D"color: #000;" class=3D"s=
tyled-by-prettify">std</span><span style=3D"color: #660;" class=3D"styled-b=
y-prettify">::</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy">size_t N</span><span style=3D"color: #660;" class=3D"styled-by-prettify=
">&gt;</span><span style=3D"color: #000;" class=3D"styled-by-prettify"><br>=
</span><span style=3D"color: #008;" class=3D"styled-by-prettify">class</spa=
n><span style=3D"color: #000;" class=3D"styled-by-prettify"> bitset<br></sp=
an><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span =
style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </spa=
n><span style=3D"color: #800;" class=3D"styled-by-prettify">// ...</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 <=
/span><span style=3D"color: #008;" class=3D"styled-by-prettify">template</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><s=
pan style=3D"color: #008;" class=3D"styled-by-prettify">typename</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> T</span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=3D"co=
lor: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 T as_integral</s=
pan><span style=3D"color: #660;" class=3D"styled-by-prettify">()</span><spa=
n style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #008;" class=3D"styled-by-prettify">const</span><span style=3D"c=
olor: #000;" class=3D"styled-by-prettify"> noexcept<br>=C2=A0 =C2=A0 </span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">{</span><span st=
yle=3D"color: #000;" class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =
=C2=A0 </span><span style=3D"color: #008;" class=3D"styled-by-prettify">sta=
tic_assert</span><span style=3D"color: #660;" class=3D"styled-by-prettify">=
(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">std</span=
><span style=3D"color: #660;" class=3D"styled-by-prettify">::</span><span s=
tyle=3D"color: #000;" class=3D"styled-by-prettify">is_integral</span><span =
style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify">T</span><span style=3D"color=
: #660;" class=3D"styled-by-prettify">&gt;::</span><span style=3D"color: #0=
00;" class=3D"styled-by-prettify">value </span><span style=3D"color: #660;"=
 class=3D"styled-by-prettify">&amp;&amp;</span><span style=3D"color: #000;"=
 class=3D"styled-by-prettify"> N </span><span style=3D"color: #660;" class=
=3D"styled-by-prettify">&lt;=3D</span><span style=3D"color: #000;" class=3D=
"styled-by-prettify"> </span><span style=3D"color: #008;" class=3D"styled-b=
y-prettify">sizeof</span><span style=3D"color: #660;" class=3D"styled-by-pr=
ettify">(</span><span style=3D"color: #000;" class=3D"styled-by-prettify">T=
</span><span style=3D"color: #660;" class=3D"styled-by-prettify">)</span><s=
pan style=3D"color: #000;" class=3D"styled-by-prettify"> </span><span style=
=3D"color: #660;" class=3D"styled-by-prettify">*</span><span style=3D"color=
: #000;" class=3D"styled-by-prettify"> </span><span style=3D"color: #066;" =
class=3D"styled-by-prettify">8</span><span style=3D"color: #660;" class=3D"=
styled-by-prettify">);</span><span style=3D"color: #000;" class=3D"styled-b=
y-prettify"><br>=C2=A0 =C2=A0 =C2=A0 =C2=A0 </span><span style=3D"color: #8=
00;" class=3D"styled-by-prettify">//...</span><span style=3D"color: #000;" =
class=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color:=
 #660;" class=3D"styled-by-prettify">}</span><span style=3D"color: #000;" c=
lass=3D"styled-by-prettify"><br>=C2=A0 =C2=A0 </span><span style=3D"color: =
#800;" class=3D"styled-by-prettify">// ...</span><span style=3D"color: #000=
;" class=3D"styled-by-prettify"><br></span><span style=3D"color: #660;" cla=
ss=3D"styled-by-prettify">};</span></div></code></div><div><br></div><div><=
br></div><div>Also it makes converting bitset to smaller integer impossible=
 at compile time. That saves us from losing bits during careless convertion=
s.</div><div><br></div><div class=3D"prettyprint" style=3D"background-color=
: rgb(250, 250, 250); border-color: rgb(187, 187, 187); border-style: solid=
; border-width: 1px; word-wrap: break-word;"><code class=3D"prettyprint"><d=
iv class=3D"subprettyprint"><span style=3D"color: #000;" class=3D"styled-by=
-prettify">std</span><span style=3D"color: #660;" class=3D"styled-by-pretti=
fy">::</span><span style=3D"color: #000;" class=3D"styled-by-prettify">bits=
et</span><span style=3D"color: #660;" class=3D"styled-by-prettify">&lt;</sp=
an><span style=3D"color: #066;" class=3D"styled-by-prettify">16</span><span=
 style=3D"color: #660;" class=3D"styled-by-prettify">&gt;</span><span style=
=3D"color: #000;" class=3D"styled-by-prettify"> bs</span><span style=3D"col=
or: #660;" class=3D"styled-by-prettify">;</span><span style=3D"color: #000;=
" class=3D"styled-by-prettify"><br>bs</span><span style=3D"color: #660;" cl=
ass=3D"styled-by-prettify">.</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify">as_integral</span><span style=3D"color: #080;" class=3D"s=
tyled-by-prettify">&lt;uint16_t&gt;</span><span style=3D"color: #660;" clas=
s=3D"styled-by-prettify">();</span><span style=3D"color: #000;" class=3D"st=
yled-by-prettify"><br>bs</span><span style=3D"color: #660;" class=3D"styled=
-by-prettify">.</span><span style=3D"color: #000;" class=3D"styled-by-prett=
ify">as_integral</span><span style=3D"color: #080;" class=3D"styled-by-pret=
tify">&lt;uint8_t&gt;</span><span style=3D"color: #660;" class=3D"styled-by=
-prettify">();</span><span style=3D"color: #000;" class=3D"styled-by-pretti=
fy"> </span><span style=3D"color: #800;" class=3D"styled-by-prettify">// CO=
MPILATION ERROR HERE!</span></div></code></div><div><br></div><div>That&#39=
;s the idea.</div></div>

<p></p>

-- <br />
You received this message because you are subscribed to the Google Groups &=
quot;ISO C++ Standard - Future Proposals&quot; group.<br />
To unsubscribe from this group and stop receiving emails from it, send an e=
mail to <a href=3D"mailto:std-proposals+unsubscribe@isocpp.org">std-proposa=
ls+unsubscribe@isocpp.org</a>.<br />
To post to this group, send email to <a href=3D"mailto:std-proposals@isocpp=
..org">std-proposals@isocpp.org</a>.<br />
To view this discussion on the web visit <a href=3D"https://groups.google.c=
om/a/isocpp.org/d/msgid/std-proposals/45a725a4-ad2e-44b4-9ed8-097de9f6eb03%=
40isocpp.org?utm_medium=3Demail&utm_source=3Dfooter">https://groups.google.=
com/a/isocpp.org/d/msgid/std-proposals/45a725a4-ad2e-44b4-9ed8-097de9f6eb03=
%40isocpp.org</a>.<br />

------=_Part_907_1612902579.1488626681611--

------=_Part_906_521102795.1488626681611--

.