<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 873: signed integral type and unsigned integral type are not clearly defined</title>
<meta property="og:title" content="Issue 873: signed integral type and unsigned integral type are not clearly defined">
<meta property="og:description" content="C++ library issue. Status: NAD Editorial">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue873.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#NAD_Editorial">NAD Editorial</a> status.</em></p>
<h3 id="873"><a href="lwg-closed.html#873">873</a>. signed integral type and unsigned integral type are not clearly defined</h3>
<p><b>Section:</b> 6.9.2 <a href="https://wg21.link/basic.fundamental">[basic.fundamental]</a> <b>Status:</b> <a href="lwg-active.html#NAD_Editorial">NAD Editorial</a>
 <b>Submitter:</b> Travis Vitek <b>Opened:</b> 2008-06-30 <b>Last modified:</b> 2016-01-28</p>
<p><b>Priority: </b>Not Prioritized
</p>
<p><b>View all issues with</b> <a href="lwg-status.html#NAD Editorial">NAD Editorial</a> status.</p>
<p><b>Discussion:</b></p>
    <p>
      Neither the term "signed integral type" nor the term "unsigned
      integral type" is defined in the core language section of the
      standard, therefore the library section should avoid its use.  The
      terms <i>signed integer type</i> and <i>unsigned integer type</i> are
      indeed defined (in 6.9.2 <a href="https://wg21.link/basic.fundamental">[basic.fundamental]</a>), thus the usages should be
      replaced accordingly.
    </p>

    <p>
      Note that the key issue here is that "signed" + "integral type" !=
      "signed integral type".
      
      The types <code>bool</code>, <code>char</code>, <code>char16_t</code>,
      <code>char32_t</code> and <code>wchar_t</code> are all listed as
      integral types, but are neither of <i>signed integer type</i> or
      <i>unsigned integer type</i>. According to 6.9 <a href="https://wg21.link/basic.types">[basic.types]</a> p7, a synonym for
      integral type is <i>integer type</i>.
      
      Given this, one may choose to assume that an <i>integral type</i> that
      can represent values less than zero is a <i>signed integral type</i>.
      Unfortunately this can cause ambiguities.
      
      As an example, if <code>T</code> is <code>unsigned char</code>, the
      expression <code>make_signed&lt;T&gt;::type</code>, is supposed to
      name a signed integral type. There are potentially two types that
      satisfy this requirement, namely <code>signed char</code> and
      <code>char</code> (assuming <code>CHAR_MIN &lt; 0</code>).
    </p>

<p><i>[
San Francisco:
]</i></p>


<blockquote><p>
Plum, Sebor to review.
</p></blockquote>

<p><i>[
Post Summit Daniel adds:
]</i></p>


<blockquote><p>
The proposed resolution needs to be "conceptualized". Currently we have
in  [concept.support] only concept <code>IntegralType</code>
for all "integral types", thus indeed the current <code>Container</code>
concept and Iterator concepts are sufficiently satisfied with "integral
types". If the changes are applied, we might ask core for concept
<code>BilateralIntegerType</code> and add proper restrictions to the library
concepts.
</p></blockquote>

  

  <p id="res-873"><b>Proposed resolution:</b></p>
    <p>
      I propose to use the terms "signed integer type" and "unsigned integer
      type" in place of "signed integral type" and "unsigned integral type"
      to eliminate such ambiguities.
    </p>
    
    <p>
      The proposed change makes it absolutely clear that the difference
      between two pointers cannot be <code>char</code> or <code>wchar_t</code>,
      but could be any of the signed integer types.
      7.6.6 <a href="https://wg21.link/expr.add">[expr.add]</a> paragraph 6...
    </p>
    <blockquote>
      <p>
      </p>
        <ol>
          <li>
            When two pointers to elements of the same array object are
            subtracted, the result is the difference of the subscripts of
            the two array elements. The type of the result is an
            implementation-defined <del>signed integral
            type</del><ins>signed integer type</ins>; this type shall be the
            same type that is defined as <code>std::ptrdiff_t</code> in the
            <code>&lt;cstdint&gt;</code> header (18.1)...
          </li>
        </ol>
    </blockquote>

    <p>
      The proposed change makes it clear that <code>X::size_type</code> and
      <code>X::difference_type</code> cannot be <code>char</code> or
      <code>wchar_t</code>, but could be one of the signed or unsigned integer
      types as appropriate.
      16.4.4.6 <a href="https://wg21.link/allocator.requirements">[allocator.requirements]</a> table 40...
    </p>
    <blockquote><p>
      Table 40: Allocator requirements
	  </p>
      <table border="1">
        <thead>
          <tr>
            <th>expression</th>
            <th>return type</th>
            <th>assertion/note/pre/post-condition</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td><code>X::size_type</code></td>
            <td>
              <del>unsigned integral type</del>
              <ins>unsigned integer type</ins>
            </td>
            <td>a type that can represent the size of the largest object in
            the allocation model.</td>
          </tr>
          <tr>
            <td><code>X::difference_type</code></td>
            <td>
              <del>signed integral type</del>
              <ins>signed integer type</ins>
            </td>
            <td>a type that can represent the difference between any two
            pointers in the allocation model.</td>
          </tr>
        </tbody>
      </table>
    </blockquote>

    <p>
      The proposed change makes it clear that <code>make_signed&lt;T&gt;::type</code>
      must be one of the signed integer types as defined in 3.9.1. Ditto for
      <code>make_unsigned&lt;T&gt;type</code> and unsigned integer types.
      21.3.9.4 <a href="https://wg21.link/meta.trans.sign">[meta.trans.sign]</a> table 48...
    </p>
    <blockquote><p>
      Table 48: Sign modifications
	  </p>
      <table border="1">
        <thead>
          <tr>
            <th>Template</th>
            <th>Comments</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td>
              <code>template &lt;class T&gt; struct make_signed;</code>
            </td>
            <td>
              If <code>T</code> names a (possibly cv-qualified) <del>signed
              integral type</del><ins>signed integer type</ins> (3.9.1) then
              the member typedef <code>type</code> shall name the type
              <code>T</code>; otherwise, if <code>T</code> names a (possibly
              cv-qualified) <del>unsigned integral type</del><ins>unsigned
              integer type</ins> then <code>type</code> shall name the
              corresponding <del>signed integral type</del><ins>signed
              integer type</ins>, with the same cv-qualifiers as
              <code>T</code>; otherwise, <code>type</code> shall name the
              <del>signed integral type</del><ins>signed integer type</ins>
              with the smallest rank (4.13) for which <code>sizeof(T) ==
              sizeof(type)</code>, with the same cv-qualifiers as
              <code>T</code>.

              <i>Requires:</i> <code>T</code> shall be a (possibly
              cv-qualified) integral type or enumeration but not a
              <code>bool</code> type.
            </td>
          </tr>
          <tr>
            <td>
              <code>template &lt;class T&gt; struct make_unsigned;</code>
            </td>
            <td>
              If <code>T</code> names a (possibly cv-qualified)
              <del>unsigned integral type</del><ins>unsigned integer
              type</ins> (3.9.1) then the member typedef <code>type</code>
              shall name the type <code>T</code>; otherwise, if
              <code>T</code> names a (possibly cv-qualified) <del>signed
              integral type</del><ins>signed integer type</ins> then
              <code>type</code> shall name the corresponding <del>unsigned
              integral type</del><ins>unsigned integer type</ins>, with the
              same cv-qualifiers as <code>T</code>; otherwise,
              <code>type</code> shall name the <del>unsigned integral
              type</del><ins>unsigned integer type</ins> with the smallest
              rank (4.13) for which <code>sizeof(T) == sizeof(type)</code>,
              with the same cv-qualifiers as <code>T</code>.

              <i>Requires:</i> <code>T</code> shall be a (possibly
              cv-qualified) integral type or enumeration but not a
              <code>bool</code> type.
            </td>
          </tr>
        </tbody>
      </table>
    </blockquote>


    <p>
      Note: I believe that the basefield values should probably be
      prefixed with <code>ios_base::</code> as they are in 28.3.4.3.3.3 <a href="https://wg21.link/facet.num.put.virtuals">[facet.num.put.virtuals]</a>

      The listed virtuals are all overloaded on signed and unsigned integer
      types, the new wording just maintains consistency.

      28.3.4.3.2.3 <a href="https://wg21.link/facet.num.get.virtuals">[facet.num.get.virtuals]</a> table 78...
    </p>
    <blockquote><p>
      Table 78: Integer Conversions
	  </p>
      <table border="1">
        <thead>
          <tr>
            <th>State</th>
            <th><code>stdio</code> equivalent</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td><code>basefield == oct</code></td>
            <td><code>%o</code></td>
          </tr>
          <tr>
            <td><code>basefield == hex</code></td>
            <td><code>%X</code></td>
          </tr>
          <tr>
            <td><code>basefield == 0</code></td>
            <td><code>%i</code></td>
          </tr>
          <tr>
            <td><del>signed integral type</del><ins>signed integer
            type</ins></td>
            <td><code>%d</code></td>
          </tr>
          <tr>
            <td><del>unsigned integral type</del><ins>unsigned integer
            type</ins></td>
            <td><code>%u</code></td>
          </tr>
        </tbody>
      </table>
    </blockquote>

    
    
    <p>
      Rationale is same as above.
      28.3.4.3.3.3 <a href="https://wg21.link/facet.num.put.virtuals">[facet.num.put.virtuals]</a> table 80...
    </p>
    <blockquote><p>
      Table 80: Integer Conversions
	  </p>
      <table border="1">
        <thead>
          <tr>
            <th>State</th>
            <th><code>stdio</code> equivalent</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td><code>basefield == ios_base::oct</code></td>
            <td><code>%o</code></td>
          </tr>
          <tr>
            <td><code>(basefield == ios_base::hex) &amp;&amp;
            !uppercase</code></td>
            <td><code>%x</code></td>
          </tr>
          <tr>
            <td><code>(basefield == ios_base::hex)</code></td>
            <td><code>%X</code></td>
          </tr>
          <tr>
            <td><code>basefield == 0</code></td>
            <td><code>%i</code></td>
          </tr>
          <tr>
            <td>for a <del>signed integral type</del><ins>signed integer
            type</ins></td>
            <td><code>%d</code></td>
          </tr>
          <tr>
            <td>for a <del>unsigned integral type</del><ins>unsigned integer
            type</ins></td>
            <td><code>%u</code></td>
          </tr>
        </tbody>
      </table>
    </blockquote>

    
    <p>
      23.2 <a href="https://wg21.link/container.requirements">[container.requirements]</a> table 80...
    </p>
    <blockquote><p>
      Table 89: Container requirements
	  </p>
      <table border="1">
        <thead>
          <tr>
            <th>expression</th>
            <th>return type</th>
            <th>operational semantics</th>
            <th>assertion/note/pre/post-condition</th>
            <th>complexity</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td><code>X::difference_type</code></td>
            <td><del>signed integral type</del><ins>signed integer type</ins></td>
            <td>&nbsp;</td>
            <td>is identical to the difference type of <code>X::iterator</code>
            and <code>X::const_iterator</code></td>
            <td>compile time</td>
          </tr>
          <tr>
            <td><code>X::size_type</code></td>
            <td><del>unsigned integral type</del><ins>unsigned integer type</ins></td>
            <td>&nbsp;</td>
            <td><code>size_type</code> can represent any non-negative value of
            <code>difference_type</code></td>
            <td>compile time</td>
          </tr>
        </tbody>
      </table>
    </blockquote>

    <p>
      24.3.4 <a href="https://wg21.link/iterator.concepts">[iterator.concepts]</a> paragraph 1...
    </p>
    <blockquote><p>
      Iterators are a generalization of pointers that allow a C++ program to
      work with different data structures (containers) in a uniform manner.
      To be able to construct template algorithms that work correctly and
      efficiently on different types of data structures, the library
      formalizes not just the interfaces but also the semantics and
      complexity assumptions of iterators. All input iterators
      <code>i</code> support the expression <code>*i</code>, resulting in a
      value of some class, enumeration, or built-in type <code>T</code>,
      called the <i>value type</i> of the iterator. All output iterators
      support the expression <code>*i = o</code> where <code>o</code> is a
      value of some type that is in the set of types that are
      <i>writable</i> to the particular iterator type of <code>i</code>. All
      iterators <code>i</code> for which the expression <code>(*i).m</code>
      is well-defined, support the expression <code>i->m</code> with the
      same semantics as <code>(*i).m</code>. For every iterator type
      <code>X</code> for which equality is defined, there is a corresponding
      <del>signed integral type</del> <ins>signed integer type</ins> called
      the <i>difference type</i> of the iterator.
    </p></blockquote>
    
    <p>
      I'm a little unsure of this change. Previously this paragraph would
      allow instantiations of <code>linear_congruential_engine</code> on
      <code>char</code>, <code>wchar_t</code>, <code>bool</code>, and other types. The
      new wording prohibits this.
      29.5.4.2 <a href="https://wg21.link/rand.eng.lcong">[rand.eng.lcong]</a> paragraph 2...
    </p>
    <blockquote><p>
      The template parameter <code>UIntType</code> shall denote an
      <del>unsigned integral type</del><ins>unsigned integer type</ins>
      large enough to store values as large as <code>m - 1</code>. If the
      template parameter <code>m</code> is 0, the modulus <code>m</code>
      used throughout this section 26.4.3.1 is
      <code>numeric_limits&lt;result_type&gt;::max()</code> plus 1.  [Note:
      The result need not be representable as a value of type
      <code>result_type</code>. --end note] Otherwise, the following
      relations shall hold: <code>a &lt; m</code> and <code>c &lt;
      m</code>.
    </p></blockquote>
    
    <p>
      Same rationale as the previous change.
      99 [rand.adapt.xor] paragraph 6...
    </p>
    <blockquote><p>
      Both <code>Engine1::result_type</code> and
      <code>Engine2::result_type</code> shall denote (possibly different)
      <del>unsigned integral types</del><ins>unsigned integer types</ins>.
      The member <i>result_type</i> shall denote either the type
      <i>Engine1::result_type</i> or the type <i>Engine2::result_type</i>,
      whichever provides the most storage according to clause 3.9.1.
    </p></blockquote>
    
    <p>
      29.5.8.1 <a href="https://wg21.link/rand.util.seedseq">[rand.util.seedseq]</a> paragraph 7...
    </p>
    <blockquote><p>
      <i>Requires:</i><code>RandomAccessIterator</code> shall meet the
      requirements of a random access iterator (24.1.5) such that
      <code>iterator_traits&lt;RandomAccessIterator&gt;::value_type</code>
      shall denote an <del>unsigned integral type</del><ins>unsigned integer
      type</ins> capable of accomodating 32-bit quantities.  
    </p></blockquote>

    <p>
      By making this change, integral types that happen to have a signed
      representation, but are not signed integer types, would no longer be
      required to use a two's complement representation. This may go against
      the original intent, and should be reviewed.
      32.5.8.2 <a href="https://wg21.link/atomics.types.operations">[atomics.types.operations]</a> paragraph 24...
    </p>
    <blockquote><p>
      <i>Remark:</i> For <del>signed integral types</del><ins>signed integer
      types</ins>, arithmetic is defined using two's complement
      representation. There are no undefined results. For address types, the
      result may be an undefined address, but the operations otherwise have
      no undefined behavior.
    </p></blockquote>
    
  




</body>
</html>
