<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>dryperspective.github.io</title>
  <subtitle>Browse aymeric&#39;s, an independent, searchable archive of readable snapshots from followed feeds, preserved in Git with aggr.</subtitle>
  <id>https://aggr.aymericbeaumet.com/sources/dryperspective.github.io/</id>
  <link rel="alternate" type="text/html" href="https://aggr.aymericbeaumet.com/sources/dryperspective.github.io/"/>
  <link rel="self" type="application/atom+xml" href="https://aggr.aymericbeaumet.com/sources/dryperspective.github.io/atom.xml"/>
  <updated>2026-10-04T12:30:26+00:00</updated>
  <author>
    <name>aymeric&#39;s</name>
  </author>
  <generator version="2.0.0" uri="https://github.com/aymericbeaumet/aggr">aggr</generator>
  <entry>
    <id>urn:aggr:item:77b70783a75dc91714284f5187c846e6779fcec4</id>
    <title type="text">The complement of true is true, except when it&#39;s false</title>
    <link rel="alternate" type="text/html" href="https://aggr.aymericbeaumet.com/items/lobste-rs/2026-10-04-the-complement-of-true-is-true-except-when-it-s-false/"/>
    <link rel="via" type="text/html" href="https://dryperspective.github.io/posts/complement-of-true/"/>
    <published>2026-10-04T12:30:26+00:00</published>
    <updated>2026-10-04T12:30:26+00:00</updated>
    <author>
      <name>dryperspective.github.io via aw1621107</name>
    </author>
    <category term="news"/>
    <category term="c++"/>
    <category term="enums"/>
    <category term="undefined-behaviour"/>
    <category term="wg21"/>
    <source>
      <title>Lobsters: Top Stories of the Past Week</title>
    </source>
    <summary type="text">Comments</summary>
    <content type="html">&lt;p&gt;I recently looked at &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2026/p4313r1.html&quot;&gt;P4313R1&lt;/a&gt;, a standards proposal paper which adds a set of bitmask operations for enums, using a C++26 annotation to opt-in. The core idea being that, to use an example from the paper, given code like the below:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C++&quot;&gt;&lt;span class=&quot;syntax-source syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c++&quot;&gt;enum class&lt;/span&gt; [[=&lt;span class=&quot;syntax-entity syntax-name syntax-enum syntax-c++&quot;&gt;std&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;:&lt;/span&gt;:&lt;span class=&quot;syntax-entity syntax-other syntax-inherited-class syntax-c++&quot;&gt;bitmask_type&lt;/span&gt;]] &lt;span class=&quot;syntax-entity syntax-other syntax-inherited-class syntax-c++&quot;&gt;Permission&lt;/span&gt; &lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;
  None    &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
  Read    &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
  Write   &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
  Execute &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;[[=std::bitmask_type]]&lt;/code&gt; annotation would automatically imbue &lt;code&gt;Permission&lt;/code&gt; with an accessible set of bitwise operations so that you as a user needn’t write them out yourself. This got me thinking about the murky underbelly of C++ integer operations. Your C++ compiler will happily compute bitwise operations for any integral type as a builtin operation. This extends to types which we don’t traditionally think of as integers, such as &lt;code&gt;wchar_t&lt;/code&gt;, the UTF character types &lt;code&gt;char8_t&lt;/code&gt; through &lt;code&gt;char32_t&lt;/code&gt;, and &lt;code&gt;bool&lt;/code&gt;. But slightly more happens here than meets the eye. Because when you attempt to perform an operation like &lt;code&gt;a | b&lt;/code&gt;, and the type of &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; is an integral type smaller than &lt;code&gt;int&lt;/code&gt;, the language does not operate on the bit patterns of &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; directly. They undergo &lt;em&gt;integral promotion&lt;/em&gt; - they are promoted up to &lt;code&gt;int&lt;/code&gt; as an intermediate state, the bit patterns of these two &lt;code&gt;int&lt;/code&gt;s are combined, and the result is returned to you, still as an &lt;code&gt;int&lt;/code&gt;.&lt;sup class=&quot;footnote-ref&quot;&gt;&lt;a href=&quot;#fn-1&quot; id=&quot;fnref-1&quot; data-footnote-ref&gt;1&lt;/a&gt;&lt;/sup&gt; Consider the below:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C++&quot;&gt;&lt;span class=&quot;syntax-source syntax-c++&quot;&gt;&lt;span class=&quot;syntax-comment syntax-line syntax-double-slash syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-c&quot;&gt;//&lt;/span&gt;Two shorts
&lt;/span&gt;&lt;span class=&quot;syntax-storage syntax-modifier syntax-c++&quot;&gt;constexpr&lt;/span&gt; &lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;short&lt;/span&gt; perm_A &lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;syntax-storage syntax-modifier syntax-c++&quot;&gt;constexpr&lt;/span&gt; &lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;short&lt;/span&gt; perm_B &lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;syntax-comment syntax-line syntax-double-slash syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-c&quot;&gt;//&lt;/span&gt;And the result type of running a bitwise operation on them is int
&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-c++&quot;&gt;static_assert&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;std&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;same_as&lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c++&quot;&gt;decltype&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;perm_A &lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;|&lt;/span&gt; perm_B&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, for the most part this is harmless - if you cast the above &lt;code&gt;perm_A | perm_B&lt;/code&gt; back to &lt;code&gt;short&lt;/code&gt; then the unnecessary bytes are truncated away and you’re left with a &lt;code&gt;short&lt;/code&gt; which contains exactly the value it would have held if you’d combined &lt;code&gt;perm_A&lt;/code&gt; and &lt;code&gt;perm_B&lt;/code&gt; as &lt;code&gt;short&lt;/code&gt; directly. And if you want to be certain that you are keeping your types consistent, and avoid the pernicious bugs of silent narrowing conversions, you can get into the habit of &lt;code&gt;static_cast&lt;/code&gt;-ing the result of your bitwise operation to its original type. The important thing here however is that integral promotion is not optional. Unlike most other areas of C++ the developer doesn’t get a choice - your types will unavoidably be promoted for these operations.&lt;/p&gt;
&lt;p&gt;The second part of what makes this a hazard for &lt;code&gt;bool&lt;/code&gt; specifically is &lt;em&gt;boolean conversion&lt;/em&gt;, a special case which does &lt;em&gt;not&lt;/em&gt; truncate but instead explicitly converts zero to &lt;code&gt;false&lt;/code&gt; and non-zero values to &lt;code&gt;true&lt;/code&gt;. For these non-zero values, whatever bit pattern was previously stored is discarded and replaced with &lt;code&gt;true&lt;/code&gt;, which has an integer value of 1. So if we take code like this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C++&quot;&gt;&lt;span class=&quot;syntax-source syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;int&lt;/span&gt; x&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;bool&lt;/span&gt; b&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and look at the generated asm (in this case from unoptimised x86-64 gcc 16.2):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-asm&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;Assembly&quot;&gt;mov     DWORD PTR [rbp-4], 10   ;Store the value of 10
cmp     DWORD PTR [rbp-4], 0    ;Then compare to 0, set ZF if x is zero
setne   al                      ;Write 1 to AL if ZF is clear
mov     BYTE PTR [rbp-5], al    ;Store the result
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The standard (specifically &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://eel.is/c++draft/conv.bool&quot;&gt;[conv.bool]&lt;/a&gt;) bases converting to &lt;code&gt;bool&lt;/code&gt; on the only possible values which &lt;code&gt;bool&lt;/code&gt; can hold - &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt;, regardless of whatever bit pattern may have originally been used to create them.&lt;/p&gt;
&lt;h2&gt;Putting it together&lt;/h2&gt;
&lt;p&gt;With all of that covered, let’s talk through what happens when you try to evaluate &lt;code&gt;~true&lt;/code&gt; and then cast the result to a &lt;code&gt;bool&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The value &lt;code&gt;true&lt;/code&gt; is promoted to an &lt;code&gt;int&lt;/code&gt; with a value of &lt;code&gt;1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The complement of &lt;code&gt;1&lt;/code&gt; as an &lt;code&gt;int&lt;/code&gt; is calculated as &lt;code&gt;-2&lt;/code&gt;, as two’s complement behaviour is required as of C++20.&lt;/li&gt;
&lt;li&gt;The value of &lt;code&gt;-2&lt;/code&gt; is then cast back down to &lt;code&gt;bool&lt;/code&gt;, undergoes boolean conversion, and since &lt;code&gt;-2&lt;/code&gt; is non-zero, becomes &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There you have it, the complement of &lt;code&gt;true&lt;/code&gt; is &lt;code&gt;true&lt;/code&gt;, or spelled in C++ &lt;code&gt;static_cast&amp;lt;bool&amp;gt;(~true) == true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This brings us back to enums. An enum is permitted to use any integral type as its underlying type, including our good friend &lt;code&gt;bool&lt;/code&gt;. So let’s define one:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C++&quot;&gt;&lt;span class=&quot;syntax-source syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c++&quot;&gt;enum class&lt;/span&gt; [[=&lt;span class=&quot;syntax-entity syntax-name syntax-enum syntax-c++&quot;&gt;std&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;:&lt;/span&gt;:&lt;span class=&quot;syntax-entity syntax-other syntax-inherited-class syntax-c++&quot;&gt;bitmask_type&lt;/span&gt;]] &lt;span class=&quot;syntax-entity syntax-other syntax-inherited-class syntax-c++&quot;&gt;boolean&lt;/span&gt; : &lt;span class=&quot;syntax-entity syntax-other syntax-inherited-class syntax-c++&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;
    &lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s also look at the bitwise complement operator as laid out in P4313R1:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C++&quot;&gt;&lt;span class=&quot;syntax-source syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-template syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-template syntax-c++&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-template syntax-c++&quot;&gt;bitmask&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;-&lt;/span&gt;like T&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-template syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;syntax-storage syntax-modifier syntax-c++&quot;&gt;constexpr&lt;/span&gt; T &lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-entity syntax-name syntax-function syntax-c++&quot;&gt;operator~&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-parameters syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-parameters syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;T &lt;span class=&quot;syntax-variable syntax-parameter syntax-c++&quot;&gt;lhs&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt; &lt;span class=&quot;syntax-storage syntax-modifier syntax-c++&quot;&gt;noexcept&lt;/span&gt; &lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;
  &lt;span class=&quot;syntax-keyword syntax-control syntax-c++&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;T&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;to_underlying&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;lhs&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;By now the workings of that operator should be a familiar shape - first we convert the enum to its underlying type (in our case &lt;code&gt;bool&lt;/code&gt;), then integral promotion is applied if that type is lower ranked than &lt;code&gt;int&lt;/code&gt;, then we perform the bitwise operation, then we cast back to the enum type. As we would expect:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C++&quot;&gt;&lt;span class=&quot;syntax-source syntax-c++&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-c++&quot;&gt;static_assert&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;~&lt;/span&gt;boolean&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;TRUE&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;==&lt;/span&gt; boolean&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;TRUE&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Godbolt &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://godbolt.org/z/PW1EEvMex&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This has all the potential to be a slightly confusing corner case in the language.&lt;/p&gt;
&lt;h2&gt;When it’s false&lt;/h2&gt;
&lt;p&gt;There is one exceptional case here which compounds the problem. If we try to run that same example in gcc, we get a different result:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C++&quot;&gt;&lt;span class=&quot;syntax-source syntax-c++&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-c++&quot;&gt;static_assert&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;~&lt;/span&gt;boolean&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;TRUE&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;==&lt;/span&gt; boolean&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;FALSE&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Godbolt &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://godbolt.org/z/xWzjarEz8&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;So what is going on with gcc? If we move the operation to runtime by defining two functions which depend on it as a runtime value:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C++&quot;&gt;&lt;span class=&quot;syntax-source syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c++&quot;&gt;enum class&lt;/span&gt; &lt;span class=&quot;syntax-entity syntax-name syntax-enum syntax-c++&quot;&gt;boolean&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt; &lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-entity syntax-other syntax-inherited-class syntax-c++&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;
    &lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-entity syntax-name syntax-function syntax-c++&quot;&gt;f&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-parameters syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-parameters syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;syntax-variable syntax-parameter syntax-c++&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-c&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;syntax-variable syntax-parameter syntax-c++&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;
    out &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-entity syntax-name syntax-function syntax-c++&quot;&gt;g&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-parameters syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-parameters syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;syntax-variable syntax-parameter syntax-c++&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt; boolean&lt;span class=&quot;syntax-keyword syntax-operator syntax-c&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;syntax-variable syntax-parameter syntax-c++&quot;&gt;out&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;
    out &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;boolean&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;x&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and look at the asm (again unoptimised x86-64), then we get:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-asm&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;Assembly&quot;&gt;&amp;quot;f(int, bool&amp;amp;)&amp;quot;:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], edi
        mov     QWORD PTR [rbp-16], rsi
        cmp     DWORD PTR [rbp-4], 0
        setne   dl                          ;same setne pattern from [conv.bool] earlier
        mov     rax, QWORD PTR [rbp-16]
        mov     BYTE PTR [rax], dl
        nop
        pop     rbp
        ret
&amp;quot;g(int, boolean&amp;amp;)&amp;quot;:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], edi
        mov     QWORD PTR [rbp-16], rsi
        mov     eax, DWORD PTR [rbp-4]
        and     eax, 1                      ;store the low bit in eax
        mov     rdx, QWORD PTR [rbp-16]
        mov     BYTE PTR [rdx], al          ;and move al to the out-param
        nop
        pop     rbp
        ret
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What we see is that when the type is not spelled &lt;code&gt;bool&lt;/code&gt;, gcc will truncate down to the lowest bit rather than perform a boolean conversion. Any even value, when cast down, will produce &lt;code&gt;boolean::FALSE&lt;/code&gt;, and any odd one will produce &lt;code&gt;boolean::TRUE&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is unique to enum types specifically, gcc generally performs consistently when handling &lt;code&gt;bool&lt;/code&gt; directly:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C++&quot;&gt;&lt;span class=&quot;syntax-source syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-modifier syntax-c++&quot;&gt;constexpr&lt;/span&gt; boolean b&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;boolean&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-c++&quot;&gt;static_assert&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;~&lt;/span&gt;b&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;false&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-c++&quot;&gt;static_assert&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-c++&quot;&gt;static_assert&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;std&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;to_underlying&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;~&lt;/span&gt;b&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;false&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-c++&quot;&gt;static_assert&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;~&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;std&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;to_underlying&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;b&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In contrast, Clang and MSVC will evaluate the result of all four of these complement-and-cast combinations as &lt;code&gt;true&lt;/code&gt;, which is what the standard says they must be. Full godbolt comparison &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://godbolt.org/z/5vK3zM7Y9&quot;&gt;here&lt;/a&gt;. This seems to be a fairly long-lived conformance bug in gcc.&lt;/p&gt;
&lt;p&gt;But there is one place in the standard where integral promotion rules go further and introduce a new vector for undefined behaviour to enter into your program when doing these bitmask operations. Consider this code:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C++&quot;&gt;&lt;span class=&quot;syntax-source syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c++&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;syntax-entity syntax-name syntax-enum syntax-c++&quot;&gt;nums&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;
    zero&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
    one&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
    two&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
    three&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;syntax-comment syntax-line syntax-double-slash syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-c&quot;&gt;//&lt;/span&gt;This is implementation defined but holds on gcc and Clang.
&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-c++&quot;&gt;static_assert&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;std&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;is_same_v&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;std&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;underlying_type_t&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;nums&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;syntax-comment syntax-line syntax-double-slash syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-c&quot;&gt;//&lt;/span&gt;nums uses an unsigned int as its base, therefore the entire domain of representable values is &amp;gt;= 0.
&lt;/span&gt;&lt;span class=&quot;syntax-comment syntax-line syntax-double-slash syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-c&quot;&gt;//&lt;/span&gt;So let&amp;#39;s test this:
&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-c++&quot;&gt;static_assert&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;~&lt;/span&gt;one &lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-comment syntax-line syntax-double-slash syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-c&quot;&gt;//&lt;/span&gt;FAILS
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Godbolt &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://godbolt.org/z/csW7GarKc&quot;&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Looking at the diagnostic, gcc gives us:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&lt;span class=&quot;code-snippet&quot;&gt;&amp;lt;source&amp;gt;:15:20: error: static assertion failed
   15 | static_assert(~one &amp;gt;= 0); //FAILS
      |               ~~~~~^~~~
  • the comparison reduces to &amp;#39;(-2 &amp;gt;= 0)&amp;#39;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So what happened here? Well, the passage in the standard which covers integral promotion, &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://eel.is/c++draft/conv.prom#3&quot;&gt;[conv.prom]&lt;/a&gt;, carves out a special bullet for unscoped enumeration types with no fixed underlying type to behave differently from integer types when promoting. If the entire range of values can be stored in an &lt;code&gt;int&lt;/code&gt;, then that is the type which it promotes to, then it tries &lt;code&gt;unsigned int&lt;/code&gt;, and if that fails it repeats this signed-then-unsigned pattern for &lt;code&gt;long&lt;/code&gt; and &lt;code&gt;long long&lt;/code&gt; until it finds a suitable type. But, where this differs from plain integer types is that it only considers the effective range of representable values; and so an enum backed by &lt;code&gt;unsigned int&lt;/code&gt; will promote to &lt;code&gt;int&lt;/code&gt; regardless of the normal conversion ranking which would forbid it for integral types. As before, the fact that you are calling the builtin operator via &lt;code&gt;~one&lt;/code&gt; will unavoidably promote it to &lt;code&gt;int&lt;/code&gt;, its complement is calculated as &lt;code&gt;-2&lt;/code&gt;, and then the comparison is performed between two &lt;code&gt;int&lt;/code&gt;s, and fails. If instead you convert to the underlying type first then you really see the asymmetry - &lt;code&gt;static_assert(~std::to_underlying(one) &amp;gt;= 0);&lt;/code&gt; succeeds, and is so vacuously true that gcc even warns about its redundancy.&lt;/p&gt;
&lt;p&gt;But this is only half the battle, and we need to talk about converting the result of our bitwise operation back to the enum type, and this is where UB creeps in. An unscoped enum with no specified underlying type defines itself in terms of a valid range of values determined by its enumerators independently of the range of whatever actual type is used by the compiler to back it. &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://eel.is/c++draft/dcl.enum&quot;&gt;[dcl.enum]&lt;/a&gt; tells us the value range of such an enum is the value range of a hypothetical integer type of width M, where M is the minimum bits required to represent all enumerators. To demonstrate, consider a few examples:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C++&quot;&gt;&lt;span class=&quot;syntax-source syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c++&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;syntax-entity syntax-name syntax-enum syntax-c++&quot;&gt;small&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt; &lt;span class=&quot;syntax-comment syntax-line syntax-double-slash syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-c&quot;&gt;//&lt;/span&gt;Range of enumerators is 0..1, so value range is that of an unsigned, one-bit integer.
&lt;/span&gt;    a &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
    b &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c++&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;syntax-entity syntax-name syntax-enum syntax-c++&quot;&gt;medium&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt; &lt;span class=&quot;syntax-comment syntax-line syntax-double-slash syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-c&quot;&gt;//&lt;/span&gt;Range of enumerators is 0..7, so value range is that of an unsigned, three-bit integer
&lt;/span&gt;    c &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
    d &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
    e &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;7&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c++&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;syntax-entity syntax-name syntax-enum syntax-c++&quot;&gt;large&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt; &lt;span class=&quot;syntax-comment syntax-line syntax-double-slash syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-c&quot;&gt;//&lt;/span&gt;Range of enumerators is -1..100, so value range is that of a signed, eight-bit integer
&lt;/span&gt;    f &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
    g &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
    h &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Even though your compiler will quite likely store these enums as &lt;code&gt;unsigned int&lt;/code&gt; and &lt;code&gt;int&lt;/code&gt;, only a subset of possible representable values is valid to use - that of the M-width integer. &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://eel.is/c++draft/expr.static.cast#8&quot;&gt;[expr.static.cast]&lt;/a&gt; in the standard makes it clear that it is undefined behaviour to cast a value outside of that range to the enum type. So, using the enumerators of the above example:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C++&quot;&gt;&lt;span class=&quot;syntax-source syntax-c++&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;small&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-comment syntax-line syntax-double-slash syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-c&quot;&gt;//&lt;/span&gt;Well-defined
&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;small&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-comment syntax-line syntax-double-slash syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-c&quot;&gt;//&lt;/span&gt;UB
&lt;/span&gt;
&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;medium&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-comment syntax-line syntax-double-slash syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-c&quot;&gt;//&lt;/span&gt;Well-defined: while not a value of an enumerator, it is within the range of an unsigned, three-bit integer
&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;medium&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-comment syntax-line syntax-double-slash syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-c&quot;&gt;//&lt;/span&gt;UB
&lt;/span&gt;
&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;large&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-comment syntax-line syntax-double-slash syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-c&quot;&gt;//&lt;/span&gt;Well-defined
&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;large&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;128&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-comment syntax-line syntax-double-slash syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-c&quot;&gt;//&lt;/span&gt;UB
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is our danger zone. The bitwise operators, in particular &lt;code&gt;operator~&lt;/code&gt;, can produce values which are out of the well-defined value range for an &lt;code&gt;enum&lt;/code&gt;, and user-defined operators which attempt to cast this value back down to the enum type can invoke UB.&lt;/p&gt;
&lt;p&gt;But, I hear you cry, what about the example earlier with &lt;code&gt;~one&lt;/code&gt;? We saw that give a value of &lt;code&gt;-2&lt;/code&gt; which is outside the value range of &lt;code&gt;nums&lt;/code&gt;. This is true, but here is where integral promotion actually saves us - &lt;code&gt;one&lt;/code&gt; was promoted to &lt;code&gt;int&lt;/code&gt; before we calculated its complement, and it was never cast back down again to invoke our UB. We only get into dangerous territory with a user-defined operator which converts the result of the operation back down to the original enum type.&lt;/p&gt;
&lt;p&gt;It is also important to note that this UB risk only applies to unscoped “plain” enums with no fixed underlying type. All scoped enum types have a fixed underlying type, even if they don’t specify it (in that case, &lt;code&gt;int&lt;/code&gt;); and all unscoped &lt;code&gt;enum&lt;/code&gt; types which do specify a fixed underlying type inherit that type’s value range instead of inventing their own.&lt;/p&gt;
&lt;h2&gt;Avoiding this in your own code&lt;/h2&gt;
&lt;p&gt;Let’s say that, like P4313, you are adding bitmask operations to enums for your own code. Now that we have more weirdness in this area of C++, how would you go about making sure that your code is correct and unconfusing? Avoiding the &lt;code&gt;bool&lt;/code&gt; case is simple - just constrain away that the underlying type can’t be &lt;code&gt;bool&lt;/code&gt;, either for all enums or for the complement operator. But the standard doesn’t come with a handy type trait or reflection metafunction to specifically detect an unscoped enum with no fixed underlying type. Fortunately we can make one:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C++&quot;&gt;&lt;span class=&quot;syntax-source syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-template syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-template syntax-c++&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-template syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c++&quot;&gt;typename&lt;/span&gt; E&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-template syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
concept unfixed_enum &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; std&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;is_enum_v&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;E&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-c++&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-c++&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;!&lt;/span&gt;requires &lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt; E&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://eel.is/c++draft/dcl.init.list#3.8&quot;&gt;[dcl.init.list]&lt;/a&gt; only permits this initialization from a scalar for enums with a fixed underlying type, and 0 is the only possible value which is representable for all possible enums. To cover the edge cases, the standard defines an enum with no enumerators as having the value range of an unsigned, one-bit integer; and the thing which excludes 1 as a possible value is &lt;code&gt;enum E{ a = -1 };&lt;/code&gt;, which has a range &lt;code&gt;[-1, 0]&lt;/code&gt;. Be sure not to forget the &lt;code&gt;std::is_enum_v&lt;/code&gt;. After all, there are many types for which &lt;code&gt;T{0}&lt;/code&gt; is ill-formed, and most of them are not enums.&lt;/p&gt;
&lt;p&gt;This post has mostly been focused on the bitwise complement operator, but the UB trap of an unfixed enum also applies to the bitwise left shift operator. If you take the route of constraining per operation, don’t let it slip your mind.&lt;/p&gt;
&lt;p&gt;This brings us back once again to P4313R1. At time of writing, the concept which constrains these operators only constrains the type to be some enumeration type annotated with &lt;code&gt;[[=std::bitmask_type]]&lt;/code&gt;. As such, it will allow confusing behaviour on enum types which are backed by &lt;code&gt;bool&lt;/code&gt;, and potential UB on plain enums with no fixed underlying type. If the authors don’t want to standardise the above init-list trick, they could constrain it on &lt;code&gt;std::is_scoped_enum&lt;/code&gt; as a conservative approach to prevent users from having easy access to the UB, since all unscoped enums can use the builtin bitwise operators anyway (albeit returning &lt;code&gt;int&lt;/code&gt;). They could also constrain the underlying type to not be &lt;code&gt;bool&lt;/code&gt; to minimise the confusion; particularly as the diagnostic which would normally get issued for complementing a &lt;code&gt;bool&lt;/code&gt; in user code would be suppressed by default if it came from a system header. I do intend to contact the authors of P4313 about this to see if they want to add these constraints to their paper.&lt;/p&gt;
&lt;h2&gt;Aside: What about floating point?&lt;/h2&gt;
&lt;p&gt;You might be wondering how the standard defines conversions of floating point numbers to these &lt;code&gt;bool&lt;/code&gt;-backed &lt;code&gt;enum&lt;/code&gt;s. It is perhaps unsurprising - &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://eel.is/c++draft/expr.static.cast#8&quot;&gt;[expr.static.cast]&lt;/a&gt; requires that the behaviour is equivalent to first converting the floating point value to the underlying type of the enum, and then converting it to the enum type; pointing the user to &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://eel.is/c++draft/conv.fpint#note-1&quot;&gt;[conv.fpint]&lt;/a&gt; which has an explicit note directing readers to our old friend [conv.bool]. Per the standard, this should mean that any floating point value other than exactly &lt;code&gt;0.0&lt;/code&gt; or &lt;code&gt;-0.0&lt;/code&gt; would convert to &lt;code&gt;boolean::TRUE&lt;/code&gt;, otherwise we end up back at &lt;code&gt;boolean::FALSE&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;So let’s start small:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C++&quot;&gt;&lt;span class=&quot;syntax-source syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c++&quot;&gt;enum class&lt;/span&gt; &lt;span class=&quot;syntax-entity syntax-name syntax-enum syntax-c++&quot;&gt;boolean&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt; &lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-entity syntax-other syntax-inherited-class syntax-c++&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;
    &lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-c++&quot;&gt;static_assert&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;boolean&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;==&lt;/span&gt; boolean&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;FALSE&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-c++&quot;&gt;static_assert&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;boolean&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;0.5&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;==&lt;/span&gt; boolean&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;TRUE&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-c++&quot;&gt;static_assert&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;boolean&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;2.5&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;==&lt;/span&gt; boolean&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;TRUE&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Godbolt &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://godbolt.org/z/1aK8Kfadv&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Both Clang and gcc reject this code. The errors are that &lt;code&gt;(boolean)2.5e+0&lt;/code&gt; is not a constant expression; and &lt;code&gt;static_cast&amp;lt;boolean&amp;gt;(0.5) == boolean::TRUE&lt;/code&gt; is wrong, and is instead equal to &lt;code&gt;boolean::FALSE&lt;/code&gt;. MSVC accepts the above code.&lt;/p&gt;
&lt;p&gt;But let’s go further and inspect what actually gets stored there. We write a function to examine the bit pattern generated from these casts, then try some values:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C++&quot;&gt;&lt;span class=&quot;syntax-source syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-entity syntax-name syntax-function syntax-c++&quot;&gt;show&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-parameters syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-parameters syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;syntax-variable syntax-parameter syntax-c++&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;
    &lt;span class=&quot;syntax-storage syntax-modifier syntax-c++&quot;&gt;const&lt;/span&gt; boolean e &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;boolean&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;d&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;char&lt;/span&gt; byte &lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;std&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-support syntax-function syntax-C99 syntax-c&quot;&gt;memcpy&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-c&quot;&gt;&amp;amp;&lt;/span&gt;byte&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-c&quot;&gt;&amp;amp;&lt;/span&gt;e&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;1&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;std&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-string syntax-quoted syntax-double syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-begin syntax-c&quot;&gt;&amp;quot;&lt;/span&gt;static_cast&amp;lt;boolean&amp;gt;({:7.1f})  stored byte {:3}   required {}&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-end syntax-c&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
               d&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt; byte&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;d &lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;0.0&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-ternary syntax-c&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-ternary syntax-c&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-entity syntax-name syntax-function syntax-c++&quot;&gt;main&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-parameters syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-parameters syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;
    &lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;0.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;0.5&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;1.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;2.5&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;3.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;256.0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;show&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;2.5&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Godbolt &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://godbolt.org/z/Phd8jvcjj&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The above code compiles without warning on all three compilers, but while MSVC again does the right thing in all cases, gcc and Clang’s behaviour is much more worrisome. Looking at the output, we see that gcc will always just truncate the value to an integer, then load that bit pattern into the resulting &lt;code&gt;boolean&lt;/code&gt;. So &lt;code&gt;2.5&lt;/code&gt; truncates to &lt;code&gt;2&lt;/code&gt; and gives a &lt;code&gt;boolean&lt;/code&gt; whose underlying bit pattern is &lt;code&gt;2&lt;/code&gt;. Clang does the same thing on unoptimised builds, but when optimisation is turned on, the truncated value then goes through the [conv.bool] transformation as normal and produces the right answer for all non-zero values outside of the range (-1, 1).&lt;/p&gt;
&lt;p&gt;This is more concerning than some funky bit patterns, however. The valid range of &lt;code&gt;boolean&lt;/code&gt; is [0, 1]. It is UB to read objects with bit patterns outside of this range. But, I hear you ask, what happens if we take these &lt;code&gt;boolean&lt;/code&gt;s and cast them back to &lt;code&gt;bool&lt;/code&gt;, triggering a boolean conversion with no initial floating point state? MSVC again does the right thing; gcc doesn’t modify the bit patterns, leaving us with &lt;code&gt;bool&lt;/code&gt; which are out of range of the type (and therefore UB to read); and Clang is where the fun happens again. Running the above code with a cast from &lt;code&gt;e&lt;/code&gt; to a &lt;code&gt;bool&lt;/code&gt;, and then memcpy-ing that &lt;code&gt;bool&lt;/code&gt; into the &lt;code&gt;unsigned char&lt;/code&gt;, we get this result for unoptimised builds:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;0.0&lt;/th&gt;
&lt;th&gt;0.5&lt;/th&gt;
&lt;th&gt;1.0&lt;/th&gt;
&lt;th&gt;2.5&lt;/th&gt;
&lt;th&gt;3.0&lt;/th&gt;
&lt;th&gt;256.0&lt;/th&gt;
&lt;th&gt;-2.5&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;required&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;gcc 14 / 15 / 16&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;254&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;clang 19 / 20 / 21&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;clang 23.1.1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Versions of Clang before 23 appear to simply perform &lt;code&gt;trunc(d) &amp;amp; 1&lt;/code&gt;; meaning that after truncation, odd numbers are &lt;code&gt;true&lt;/code&gt; and even numbers are &lt;code&gt;false&lt;/code&gt;. Clang 23 performs &lt;code&gt;(trunc(d) % 256) != 0&lt;/code&gt;, narrowing to a byte first. So &lt;code&gt;256.0&lt;/code&gt; becomes &lt;code&gt;FALSE&lt;/code&gt; and &lt;code&gt;257.0&lt;/code&gt; becomes &lt;code&gt;TRUE&lt;/code&gt;. Optimised builds act as before - truncating then doing the proper boolean conversion.&lt;/p&gt;
&lt;p&gt;Ultimately this all comes to a rather absurd head. Consider the below code:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;code-snippet&quot; data-language=&quot;C++&quot;&gt;&lt;span class=&quot;syntax-source syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-preprocessor syntax-include syntax-c++&quot;&gt;&lt;span class=&quot;syntax-keyword syntax-control syntax-import syntax-include syntax-c++&quot;&gt;#include&lt;/span&gt; &lt;span class=&quot;syntax-string syntax-quoted syntax-other syntax-lt-gt syntax-include syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;print&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;
&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c++&quot;&gt;enum class&lt;/span&gt; &lt;span class=&quot;syntax-entity syntax-name syntax-enum syntax-c++&quot;&gt;boolean&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt; &lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;syntax-entity syntax-other syntax-inherited-class syntax-c++&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;
    &lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;FALSE&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;TRUE&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-enum syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;syntax-comment syntax-line syntax-double-slash syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-comment syntax-c&quot;&gt;//&lt;/span&gt;Force this to be runtime
&lt;/span&gt;boolean &lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-entity syntax-name syntax-function syntax-c++&quot;&gt;make&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-parameters syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-parameters syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;double&lt;/span&gt; &lt;span class=&quot;syntax-variable syntax-parameter syntax-c++&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;
    &lt;span class=&quot;syntax-keyword syntax-control syntax-c++&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;boolean&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;d&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;

&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-entity syntax-name syntax-function syntax-c++&quot;&gt;main&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-parameters syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-parameters syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt; &lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-begin syntax-c++&quot;&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;
    &lt;span class=&quot;syntax-storage syntax-modifier syntax-c++&quot;&gt;const&lt;/span&gt; boolean e &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;make&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;2.5&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;std&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-string syntax-quoted syntax-double syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-begin syntax-c&quot;&gt;&amp;quot;&lt;/span&gt;e == boolean::TRUE  : {}&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-end syntax-c&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt; e &lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;==&lt;/span&gt; boolean&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;TRUE&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;std&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-string syntax-quoted syntax-double syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-begin syntax-c&quot;&gt;&amp;quot;&lt;/span&gt;e == boolean::FALSE : {}&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-end syntax-c&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt; e &lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;==&lt;/span&gt; boolean&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;FALSE&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;syntax-storage syntax-modifier syntax-c++&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;bool&lt;/span&gt; b &lt;span class=&quot;syntax-keyword syntax-operator syntax-assignment syntax-c&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;syntax-keyword syntax-operator syntax-word syntax-cast syntax-c++&quot;&gt;static_cast&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-begin syntax-c++&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;syntax-storage syntax-type syntax-c&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-generic syntax-end syntax-c++&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;e&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;std&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-string syntax-quoted syntax-double syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-begin syntax-c&quot;&gt;&amp;quot;&lt;/span&gt;b == true  : {}&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-end syntax-c&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt; b &lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;true&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;std&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-string syntax-quoted syntax-double syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-begin syntax-c&quot;&gt;&amp;quot;&lt;/span&gt;b == false : {}&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-end syntax-c&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt; b &lt;span class=&quot;syntax-keyword syntax-operator syntax-comparison syntax-c&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-language syntax-c&quot;&gt;false&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;std&lt;span class=&quot;syntax-punctuation syntax-accessor syntax-c++&quot;&gt;::&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-variable syntax-function syntax-c++&quot;&gt;println&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-begin syntax-c++&quot;&gt;(&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-string syntax-quoted syntax-double syntax-c&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-begin syntax-c&quot;&gt;&amp;quot;&lt;/span&gt;b + 0      : {}&lt;span class=&quot;syntax-punctuation syntax-definition syntax-string syntax-end syntax-c&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-separator syntax-c++&quot;&gt;,&lt;/span&gt; b &lt;span class=&quot;syntax-keyword syntax-operator syntax-arithmetic syntax-c&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;syntax-constant syntax-numeric syntax-c++&quot;&gt;0&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function-call syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-group syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-group syntax-end syntax-c++&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-punctuation syntax-terminator syntax-c++&quot;&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;syntax-meta syntax-function syntax-c++&quot;&gt;&lt;span class=&quot;syntax-meta syntax-block syntax-c++&quot;&gt;&lt;span class=&quot;syntax-punctuation syntax-section syntax-block syntax-end syntax-c++&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Godbolt &lt;a target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; href=&quot;https://godbolt.org/z/T7zMqGo8j&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;MSVC again leads the pack in giving the correct answer. Clang gets it exactly wrong and thinks that &lt;code&gt;e&lt;/code&gt; is &lt;code&gt;FALSE&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt;. gcc takes things up a notch, by providing an instance of an &lt;code&gt;enum&lt;/code&gt; which compares equal to all of its enumerators, and a &lt;code&gt;bool&lt;/code&gt; which is neither &lt;code&gt;true&lt;/code&gt; nor &lt;code&gt;false&lt;/code&gt;, until you turn on the optimiser and get a &lt;code&gt;bool&lt;/code&gt; which is both &lt;code&gt;true&lt;/code&gt; and &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;And to hit all the obligatory targets of any conversation on floating point, infinity and NaN show as &lt;code&gt;0&lt;/code&gt; and become &lt;code&gt;FALSE&lt;/code&gt; as &lt;code&gt;boolean&lt;/code&gt; and so cast to &lt;code&gt;false&lt;/code&gt; as &lt;code&gt;bool&lt;/code&gt; on gcc and Clang; and give &lt;code&gt;1&lt;/code&gt; and therefore &lt;code&gt;TRUE&lt;/code&gt; and &lt;code&gt;true&lt;/code&gt; on MSVC.&lt;/p&gt;
&lt;p&gt;In lighter news, Clang trunk seems to have fixed the above example to behave correctly, so some of the issues described in this section should be patched out soon.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;What did we learn from all this? Perhaps that even sensible and uncontentious pure-library-level papers such as P4313 should be on their guard against a footgun from some exotic C++ edge case. Or perhaps, in more practical terms:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Integral promotion is unavoidable. If you think you are operating on an integer which is smaller than &lt;code&gt;int&lt;/code&gt;, there’s a good chance it became an &lt;code&gt;int&lt;/code&gt; right under your nose.&lt;/li&gt;
&lt;li&gt;The bitwise complement of a &lt;code&gt;bool&lt;/code&gt; is always &lt;code&gt;true&lt;/code&gt;, even when wrapped in an enum. However you should not rely on this behaviour as gcc has a longstanding bug which gets this wrong (or right, if you prefer logic to C++).&lt;/li&gt;
&lt;li&gt;Unscoped enumeration types with no fixed underlying type have a range of valid values which may be smaller than that of whatever type actually underlies them.&lt;/li&gt;
&lt;/ul&gt;
&lt;section class=&quot;footnotes&quot; data-footnotes&gt;
&lt;ol&gt;
&lt;li id=&quot;fn-1&quot;&gt;
&lt;p&gt;To be clear, the ranking order of integral promotion is more complex than just “convert to &lt;code&gt;int&lt;/code&gt;”. For an integer type of lower conversion rank (not size) than &lt;code&gt;int&lt;/code&gt;, if all values of that type can be represented as &lt;code&gt;int&lt;/code&gt; then &lt;code&gt;int&lt;/code&gt; is chosen. Otherwise &lt;code&gt;unsigned int&lt;/code&gt; is chosen. In practice this will usually come out as &lt;code&gt;int&lt;/code&gt;; but on implementations where &lt;code&gt;int&lt;/code&gt; and &lt;code&gt;short&lt;/code&gt; are the same size, &lt;code&gt;unsigned short&lt;/code&gt; will promote directly to &lt;code&gt;unsigned int&lt;/code&gt;. And for other types such as the charN_t family, conversion can proceed to longer integer types such as &lt;code&gt;long&lt;/code&gt; and &lt;code&gt;long long&lt;/code&gt;. &lt;code&gt;bool&lt;/code&gt; is singled out as a special case and always promotes to &lt;code&gt;int&lt;/code&gt;. &lt;a href=&quot;#fnref-1&quot; class=&quot;footnote-backref&quot; data-footnote-backref data-footnote-backref-idx=&quot;1&quot; aria-label=&quot;Back to reference 1&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content>
  </entry>
</feed>
