<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
        <title>A Proposal to add wide_int Class</title>
        <meta content="http://schemas.microsoft.com/intellisense/ie5" name="vs_targetSchema">
        <meta http-equiv="Content-Language" content="en-us">
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

        <style type="text/css">
            .addition { color: green; }
            .right { float:right; }
            .changed-deleted { background-color: #CFF0FC ; text-decoration: line-through; display: none; }
            .addition.changed-deleted { color: green; background-color: #CFF0FC ; text-decoration: line-through; text-decoration: black double line-through; display: none; }
            .changed-added { background-color: #CFF0FC ;}
            .notes { background-color: #80D080 ;}
            pre { line-height: 1.2; font-size: 10pt; margin-top: 25px; }
            .desc { margin-left: 35px; margin-top: 10px; padding:0; white-space: normal; }
            body {max-width: 1024px; margin-left: 25px;}
            .cppkeyword { color: blue; }
            .cppcomment { color: green; }
            .cppcomment > .cppkeyword{ color: green; }
            .cpptext { color: #2E8B57; }
        </style>
    </head>
    <body bgcolor="#ffffff">
        <address>Document number: P0539R4</address>
        <address>Project: Programming Language C++</address>
        <address>Audience: SG6 Numerics, Library Evolution</address>
        <address>&nbsp;</address>
        <address>Igor Klevanets &lt;<a href="mailto:cerevra@yandex.ru">cerevra@yandex.ru</a>&gt;, &lt;<a href="mailto:cerevra@yandex-team.ru">cerevra@yandex-team.ru</a>&gt;</address>
        <address>Antony Polukhin &lt;<a href="mailto:antoshkka@gmail.com">antoshkka@gmail.com</a>&gt;, &lt;<a href="mailto:antoshkka@yandex-team.ru">antoshkka@yandex-team.ru</a>&gt;</address>
        <address>&nbsp;</address>
        <address>Date: 2018-05-03</address>
        <h1>A Proposal to add wide_int Template Class</h1>

        <p class='changed-added'>Significant changes to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0539r3.html">P0539R3</a> are marked with blue.<p>
        <p><input type="checkbox" id="show_deletions" onchange="show_hide_deleted()"> Show deleted lines from P0539R3.</p>
        <p class='notes'>Green lines are notes for the <b>editor</b> or for the <b>SG6</b>/<b>LEWG</b>/<b>LWG</b> that must not be treated as part of the wording.</p>
        <h2>I. Introduction and Motivation</h2>
        <p>Current standard provides signed and unsigned int8_t, int16_t, int32_t, int64_t. It is usually enough for every day tasks, but sometimes appears a need in big numbers: for cryptography, IPv6, very big counters etc. Non-standard type __int128 which is provided by gcc and clang illuminates this need. But there is no cross-platform solution and no way to satisfy future needs in even more big numbers.</p>
        <p>This is an attempt to solve the problem in a generic way on a library level and provide wording for <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0104r0.html">P0104R0: Multi-Word Integer Operations and Types</a>.</p>
        <p>A proof of concept implementation available at: <a href="https://github.com/cerevra/int/tree/master/v3">https://github.com/cerevra/int/tree/master/v3</a>.
        </p>

        <h2>II. Changelog</h2>
        <p class='changed-added'>Differences with P0539R3:</p>
        <ul class='changed-added'>
            <li>More paragraphs in "III. Design and paper limitations"</li>
            <li>Added requirements on wide_integer alignment and layout</li>
            <li>Dropped the <code>explicit</code> from <code>operator bool()</code></li>
            <li>Permitted implementations to add overloads (mostly for adding explicit overloads that do not generate warnings)</li>
        </ul>
        <p>Differences with P0539R2:</p>
        <ul>
            <li><strong>"Bits" won in the discussion "Words vs Bytes vs Bits" in Albuquerque</strong></li>
            <li>Changed "MachineWords" to "Bits"</li>
            <li>Interoperability with other types moved to a separate paper</li>
            <li>Removed <code>signedness</code> scoped enum</li>
        </ul>
        <p>Differences with P0539R1:</p>
        <ul>
            <li>Added a discussion on "Words vs Bytes vs Bits"</li>
        </ul>
        <p>Differences with P0539R0:</p>
        <ul>
            <li>Reworked the proposal for simpler integration with other Numerics proposals:
            <ul>
                <li>Added an interoperability section [numeric.interop]</li>
                <li><code>Arithmetic</code> and <code>Integral</code> concepts were moved to [numeric.requirements] as they seem widely useful</li>
                <li>Binary non-member operations that accept <code>Arithmetic</code> or <code>Integral</code> parameter were changed to accept two <code>Arithmetic</code> or <code>Integral</code> parameters respectively and moved to [numeric.interop]</li>
                <li><code>int128_t</code> and other aliases now depend on <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0102r0.html">P0102R0</a></li>
            </ul>
            </li>
            <li>Renamed <code>wide_int</code> to <code>wide_integer</code></li>
            <li><code>wide_integer</code> now uses machine words count as a template parameter, not bits count</li>
            <li>Removed not allowed type traits specializations</li>
            <li>Added <code>to_chars</code> and <code>from_chars</code></li>
        </ul>

        <h2>III. Design and paper limitations</h2>
        <p><code>wide_integer</code> is designed to be as close as possible to built-in integral types:</p>
        <ul>
            <li>it does not allocate memory</li>
            <li>it is a standard layout type</li>
            <li>it is trivially copyable</li>
            <li>it is trivially desctructible</li>
            <li>it is constexpr usable</li>
        </ul>
        <p><code>wide_integer</code> is <b>not</b> a metafunction. Such metafunctions are discussed in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0102r0.html">P0102R0</a>.</p>
        <p><code>wide_integer</code> does <b>not</b> add <code>noexcept</code> to operations that have UB for built-in types. Operations that have UB traditionally are not marked
        with <code>noexcept</code> by LWG. Attempt to change that behavior may be done in separate paper.</p>

        <p>In this proposal we concentrate on the <code>wide_integer</code> class that uses machine words under the cover. Such implementations allow you to get best performance
        and leave behind some design questions, like "Is <code>(sizeof(wide_integer&lt;X&gt;)&nbsp;==&nbsp;X&nbsp;/&nbsp;CHAR_BITS)</code> or not?".</p>
        <p>However, we do not wish to shut the door close for extending the abilities of the <code>wide_integer</code> class. Some users may wish to see unit40_t, or unit48_t.</p>
        <p>We insist on <b>interface that allows specifying integers not representable by machine words count</b>. Such extensions of functionality may be discussed in separate papers.</p>
<div class="changed-added">
        <p><b><code>wide_integer</code> mimics the behavior of <code>int</code></b>. Because of that <code>wide_int&lt;128&gt; * wide_int&lt;128&gt;</code>
        results in <code>wide_int&lt;128&gt;</code>, not <code>wide_int&lt;256&gt;</code>. There are separate proposals for integers that
        are <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0828r0.md">elastic (P0828R0)</a>
        or <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0228r0.pdf">safe (P0228R0)</a>.</p>

        <p>Non template aliases for integers of particular width (for example <code>int128_t</code>)
        are handled in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0102r0.html">separate paper P0102R0</a>. There was an implicit 
        request from LEWG to remove those aliases from this paper, as they were rising a lot of questions on some platforms.</p>

        <p>Interoperability with other arithmetic types was moved to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0880r0.html">a separate paper P0880R0</a>.</p>

        <p>We double checked that <code>constexpr</code> on default constructor does not require zero initialization in non constexpr contexts and still allows zero initialization if explicitly asked:</p>
        <pre>
int main() {
     //constexpr wide_integer&lt;128, unsigned&gt; wi;   // Not initialized in constexpr context - compile time error
     wide_integer&lt;128, unsigned&gt; wi_no_init;       // Not initialized - OK
     constexpr wide_integer&lt;128, unsigned&gt; wi{};   // Zero initialized - OK
}
        </pre>

        <p>Current revision of the paper mimics behavior of <code>int</code> even in cases that are considered dangerous.
        It is possible to make <code>wide_integer</code> type more safe by making explicit:</p>
        <ul>
            <li>Conversion from any signed to any unsigned type.</li>
            <li>Narrowing conversions.</li>
            <li>Conversion to and from floating point types.</li>
            <li>Conversion to bool.</li>
        </ul>

        <p>Such change will break the compatibility of <code>wide_integer</code> and <code>int</code>. Consider the case, when you have some template function 
        <code>foo(Arithmetic a)</code> that works with arithmetic types. Function is huge and it was developed a long time ago. If interface of <code>wide_integer</code> is same as the
        interface of <code>int</code> then <code>foo()</code> could work with it. But if we make some of
        the conversions explicit, then <code>foo()</code> function must be adjusted.</p>

        <p>Also note that adding <code>explicit</code> would affect only <code>wide_integer</code>s, while there could be a better solution for all the integral types.
        For example all the integrals could be fixed by
        some <code>safe_integer&lt;Integral&gt;</code> class, that is very explicit and does additional checks on demand. In that case adding restrictions into <code>wide_integer</code>
        would just break the interface compatibility with <code>int</code> without big benefit.</p>
</div>

        <h2>IV. Proposed wording</h2>
<div class="notes">
<p><b><i>[Note:</i></b> 
  <p>Here and below we rely on <code>Arithmetic</code> and <code>Integral</code> that are defined in P0880 in [numeric.requirements] as:</p>
  <p>Functions that accept template parameters starting with <code>Arithmetic</code> shall not participate in overload resolution unless <code>std::numeric_limits&lt;Arithmetic&gt;::is_specialized</code> is true.</p>
  <p>Functions that accept template parameters starting with <code>Integral</code> shall not participate in overload resolution unless <code>std::numeric_limits&lt;Integral&gt;::is_integer</code> is true.</p>

<p><i><b>- end note]</b></i></p>

</div>

        

<h3>18.3.4 Class template numeric_limits<span class="right">[numeric.limits]</span></h3>
<p class="notes"><b><i>[Note to editor:</i></b> Add the following sentence after the sentence "Specializations shall be provided for each arithmetic type, both floating-point and integer, including bool." (first sentence in fourth paragraph in [numeric.limits]) <i><b>- end note]</b></i></p>
<p>Specializations shall be also provided for <code>wide_integer</code> type. <i>[Note:</i> If there is a built-in integral type <code>Integral</code> that has the same signedness and width as <code>wide_integer&lt;Bits, S&gt;</code>, then <code>numeric_limits&lt;wide_integer&lt;Bits, S&gt;&gt;</code> specialized in the same way as <code>numeric_limits&lt;Integral&gt;</code><i>- end note]</i> </p>

<h3>26.??.1 Header &lt;wide_integer&gt; synopsis<span class="right">[numeric.wide_integer.syn]</span></h3>
<pre>namespace std {

  // 26.??.2 class template wide_integer
  template&lt;size_t Bits, typename S&gt; class wide_integer;

  // 26.??.?? type traits specializations
  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  struct common_type&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;;

  template&lt;size_t Bits, typename S, typename Arithmetic&gt;
  struct common_type&lt;wide_integer&lt;Bits, S&gt;, Arithmetic&gt;;

  template&lt;typename Arithmetic, size_t Bits, typename S&gt;
  struct common_type&lt;Arithmetic, wide_integer&lt;Bits, S&gt;&gt;
    : common_type&lt;wide_integer&lt;Bits, S&gt;, Arithmetic&gt;
  ;

  // 26.??.?? unary operations
  template&lt;size_t Bits, typename S&gt; constexpr wide_integer&lt;Bits, S&gt; operator~(const wide_integer&lt;Bits, S&gt;&amp; val) noexcept;
  template&lt;size_t Bits, typename S&gt; constexpr wide_integer&lt;Bits, S&gt; operator-(const wide_integer&lt;Bits, S&gt;&amp; val) noexcept(is_unsigned_v&lt;S&gt;);
  template&lt;size_t Bits, typename S&gt; constexpr wide_integer&lt;Bits, S&gt; operator+(const wide_integer&lt;Bits, S&gt;&amp; val) noexcept(is_unsigned_v&lt;S&gt;) noexcept;

  // 26.??.?? binary operations
  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
    constexpr operator*(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs);

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
    constexpr operator/(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs);

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
    constexpr operator+(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept(is_unsigned_v&lt;S&gt;);

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
    constexpr operator-(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept(is_unsigned_v&lt;S&gt;);

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
    constexpr operator%(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs);

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
    constexpr operator&amp;(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
    constexpr operator|(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
    constexpr  operator^(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  template&lt;size_t Bits, typename S&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, size_t&gt;
    constexpr  operator&lt;&lt;(const wide_integer&lt;Bits, S&gt;&amp; lhs, size_t rhs);

  template&lt;size_t Bits, typename S&gt;
    common_type_t&lt;wide_integer&lt;Bits, S&gt;, size_t&gt;
    constexpr  operator&gt;&gt;(const wide_integer&lt;Bits, S&gt;&amp; lhs, size_t rhs);

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    constexpr bool operator&lt;(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    constexpr bool operator&gt;(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    constexpr bool operator&lt;=(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    constexpr bool operator&gt;=(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    constexpr bool operator==(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
    constexpr bool operator!=(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;

  // 26.??.?? numeric conversions
  template&lt;size_t Bits, typename S&gt; std::string to_string(const wide_integer&lt;Bits, S&gt;&amp; val);
  template&lt;size_t Bits, typename S&gt; std::wstring to_wstring(const wide_integer&lt;Bits, S&gt;&amp; val);

  // 26.??.?? iostream specializations
  template&lt;class Char, class Traits, size_t Bits, typename S&gt;
  basic_ostream&lt;Char, Traits&gt;&amp; operator&lt;&lt;(basic_ostream&lt;Char, Traits&gt;&amp; os, const wide_integer&lt;Bits, S&gt;&amp; val);

  template&lt;class Char, class Traits, size_t Bits, typename S&gt;
  basic_istream&lt;Char, Traits&gt;&amp; operator&gt;&gt;(basic_istream&lt;Char, Traits&gt;&amp; is, wide_integer&lt;Bits, S&gt;&amp; val) noexcept;

  // 26.??.?? hash support
  template&lt;class T&gt; struct hash;
  template&lt;size_t Bits, typename S&gt; struct hash&lt;wide_integer&lt;Bits, S&gt;&gt;;


  template &lt;size_t Bits, typename S&gt;
  to_chars_result to_chars(char* first,
                           char* last,
                           const wide_integer&lt;Bits, S&gt;&amp; value,
                           int base = 10);

  template &lt;size_t Bits, typename S&gt;
  from_chars_result from_chars(const char* first,
                               const char* last,
                               wide_integer&lt;Bits, S&gt;&amp; value,
                               int base = 10);

  template &lt;size_t Bits&gt;
  using wide_int = wide_integer&lt;Bits, signed&gt;;

  template &lt;size_t Bits&gt;
  using wide_uint = wide_integer&lt;Bits, unsigned&gt;
</pre>
<p class="notes"><b><i>[Note:</i></b> <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0102r0.html">P0102R0</a> 
proposal with <code>exact_2int</code>, <code>fast_2int</code>, <code>least_2int</code>,
<code>exact_2uint</code>, <code>fast_2uint</code>, <code>least_2uint</code> requires additional specializations for <code>wide_integer</code>.
 <i><b>- end note]</b></i></p>

<pre>
  // optional literals
  inline namespace literals {
  inline namespace wide_int_literals {

  constexpr wide_int&lt;128&gt; operator &quot;&quot; _int128(const char*);
  constexpr wide_int&lt;256&gt; operator &quot;&quot; _int256(const char*);
  constexpr wide_int&lt;512&gt; operator &quot;&quot; _int512(const char*);
  constexpr wide_uint&lt;128&gt; operator &quot;&quot; _uint128(const char*);
  constexpr wide_uint&lt;256&gt; operator &quot;&quot; _uint256(const char*);
  constexpr wide_uint&lt;512&gt; operator &quot;&quot; _uint512(const char*);

  } // namespace wide_int_literals
  } // namespace literals
}
</pre>
<p>The header &lt;wide_integer&gt; defines class template <code>wide_integer</code> and a set of operators for representing and manipulating integers of specified width.</p><pre>[Example:
    using int128_t = wide_int&lt;128&gt;;
    constexpr int128_t c = std::numeric_limits&lt;int128_t&gt;::min();
    static_assert(c == 0x80000000000000000000000000000000_uint128);

    int256_t a = 13;
    a += 0xFF;
    a *= 2.0;
    a -= 12_int128;
    assert(a &gt; 0);
]</pre>


<h3>26.??.2 Template class wide_integer overview<span class="right">[numeric.wide_integer.overview]</span></h3>
<pre>namespace std {
  template&lt;size_t Bits, typename S&gt;
  class wide_integer {
  public:
    // 26.??.2.?? construct:
    constexpr wide_integer() noexcept = default;
    constexpr wide_integer(const wide_integer&lt;Bits, S&gt;&amp; ) noexcept = default;
    template&lt;typename Arithmetic&gt; constexpr wide_integer(const Arithmetic&amp; other) noexcept;
    template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer(const wide_integer&lt;Bits2, S2&gt;&amp; other) noexcept;

    // 26.??.2.?? assignment:
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator=(const wide_integer&lt;Bits, S&gt;&amp; ) noexcept = default;
    template&lt;typename Arithmetic&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator=(const Arithmetic&amp; other) noexcept;
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator=(const wide_integer&lt;Bits2, S2&gt;&amp; other) noexcept;

    // 26.??.2.?? compound assignment:
    template&lt;typename Arithmetic&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator*=(const Arithmetic&amp;);
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator*=(const wide_integer&lt;Bits2, S2&gt;&amp;);

    template&lt;typename Arithmetic&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator/=(const Arithmetic&amp;);
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator/=(const wide_integer&lt;Bits2, S2&gt;&amp;);

    template&lt;typename Arithmetic&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator+=(const Arithmetic&amp;) noexcept(is_unsigned_v&lt;S&gt;);
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator+=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept(is_unsigned_v&lt;S&gt;);

    template&lt;typename Arithmetic&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator-=(const Arithmetic&amp;) noexcept(is_unsigned_v&lt;S&gt;);
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator-=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept(is_unsigned_v&lt;S&gt;);

    template&lt;typename Integral&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator%=(const Integral&amp;);
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator%=(const wide_integer&lt;Bits2, S2&gt;&amp;);

    template&lt;typename Integral&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator&amp;=(const Integral&amp;) noexcept;
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator&amp;=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept;

    template&lt;typename Integral&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator|=(const Integral&amp;) noexcept;
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator|=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept;

    template&lt;typename Integral&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator^=(const Integral&amp;) noexcept;
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator^=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept;

    template&lt;typename Integral&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator&lt;&lt;=(const Integral&amp;);
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator&lt;&lt;=(const wide_integer&lt;Bits2, S2&gt;&amp;);

    template&lt;typename Integral&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator&gt;&gt;=(const Integral&amp;) noexcept;
    template&lt;size_t Bits2, typename S2&gt;
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator&gt;&gt;=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept;

    constexpr wide_integer&lt;Bits, S&gt;&amp; operator++() noexcept(is_unsigned_v&lt;S&gt;);
    constexpr wide_integer&lt;Bits, S&gt; operator++(int) noexcept(is_unsigned_v&lt;S&gt;);
    constexpr wide_integer&lt;Bits, S&gt;&amp; operator--() noexcept(is_unsigned_v&lt;S&gt;);
    constexpr wide_integer&lt;Bits, S&gt; operator--(int) noexcept(is_unsigned_v&lt;S&gt;);

    // 26.??.2.?? observers:
    template &lt;typename Arithmetic&gt; constexpr operator Arithmetic() const noexcept;
    <span class="changed-deleted">constexpr explicit operator bool() const noexcept;
</span>
  private:
    byte data[Bits / CHAR_BITS]; // exposition only
  };
}</pre>
<p>The class template <code>wide_integer&lt;size_t Bits, typename S&gt;</code> is a trivial standard layout class that behaves as an integer type
of a compile time specified bitness.</p>
<p>Template parameter <code>Bits</code> specifies exact <i>bits</i> count to store the integer value. <code>Bits % (sizeof(int) * CHAR_BITS)</code> is eqaul to 0.
<code>sizeof(wide_integer&lt;Bits, unsigned&gt;)</code> and <code>sizeof(wide_integer&lt;Bits, signed&gt;)</code> are required to
be equal to <code>Bits * CHAR_BITS</code>.</p>

<p class="changed-added">When size of <code>wide_integer</code> is equal to a size of builtin integral type then the alignment and layout of that
<code>wide_integer</code> is equal to the alignment and layout of the builtin type.</p>

<p>Template parameter <code>S</code> specifies signedness of the stored integer value and is either <code>signed</code> or <code>unsigned</code>.</p>

<div class="changed-added">
<p>Implementations are permitted to add explicit conversion operators and explicit or implicit constructors for <code>Arithmetic</code> and for <code>Integral</code> types.</p>
<p><i>[Example:</i></p><pre>
    template &lt;class Arithmetic&gt;
        [[deprecated("Implicit conversions to builtin arithmetic types are not safe!")]]
    constexpr operator Arithmetic() const noexcept;

    explicit constexpr operator bool() const noexcept;
    explicit constexpr operator int() const noexcept;
    ...</pre><p><i>— end example ]</i></p>
</div>


<h4>26.??.2.?? wide_integer constructors <span class="right">[numeric.wide_integer.cons]</span></h4>
<pre>constexpr wide_integer() noexcept = default;</pre>
<div class="desc"><i>Effects:</i> A Constructs an object with undefined value.</div>

<pre>template&lt;typename Arithmetic&gt; constexpr wide_integer(const Arithmetic&amp; other) noexcept;</pre>
<div class="desc"><i>Effects:</i> Constructs an object from <code>other</code> using the integral conversion rules [conv.integral].</div>

<pre>template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer(const wide_integer&lt;Bits2, S2&gt;&amp; other) noexcept;</pre>
<div class="desc"><i>Effects:</i> Constructs an object from <code>other</code> using the integral conversion rules [conv.integral].</div>

<h4>26.??.2.?? wide_integer assignments <span class="right">[numeric.wide_integer.assign]</span></h4>
<pre>template&lt;typename Arithmetic&gt;
constexpr wide_integer&lt;Bits, S&gt;&amp; operator=(const Arithmetic&amp; other) noexcept;</pre>
<div class="desc"><i>Effects:</i> Constructs an object from <code>other</code> using the integral conversion rules [conv.integral].</div>

<pre>template&lt;size_t Bits2, typename S2&gt;
constexpr wide_integer&lt;Bits, S&gt;&amp; operator=(const wide_integer&lt;Bits2, S2&gt;&amp; other) noexcept;</pre>
<div class="desc"><i>Effects:</i> Constructs an object from <code>other</code> using the integral conversion rules [conv.integral].</div>

<h4>26.??.2.?? wide_integer compound assignments <span class="right">[numeric.wide_integer.cassign]</span></h4>
<pre>template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator*=(const wide_integer&lt;Bits2, S2&gt;&amp;);
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator/=(const wide_integer&lt;Bits2, S2&gt;&amp;);
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator+=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept(is_unsigned_v&lt;S&gt;);
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator-=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept(is_unsigned_v&lt;S&gt;);
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator%=(const wide_integer&lt;Bits2, S2&gt;&amp;);
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator&amp;=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept;
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator|=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept;
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator^=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept;
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator&lt;&lt;=(const wide_integer&lt;Bits2, S2&gt;&amp;);
template&lt;size_t Bits2, typename S2&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator&gt;&gt;=(const wide_integer&lt;Bits2, S2&gt;&amp;) noexcept;
constexpr wide_integer&lt;Bits, S&gt;&amp; operator++() noexcept(is_unsigned_v&lt;S&gt;);
constexpr wide_integer&lt;Bits, S&gt; operator++(int) noexcept(is_unsigned_v&lt;S&gt;);
constexpr wide_integer&lt;Bits, S&gt;&amp; operator--() noexcept(is_unsigned_v&lt;S&gt;);
constexpr wide_integer&lt;Bits, S&gt; operator--(int) noexcept(is_unsigned_v&lt;S&gt;);</pre>
<div class="desc"><i>Effects:</i> Behavior of the above operators is similar to operators for built-in integral types.</div>

<pre>template&lt;typename Arithmetic&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator*=(const Arithmetic&amp;);
template&lt;typename Arithmetic&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator/=(const Arithmetic&amp;);
template&lt;typename Arithmetic&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator+=(const Arithmetic&amp;) noexcept(is_unsigned_v&lt;S&gt;);
template&lt;typename Arithmetic&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator-=(const Arithmetic&amp;) noexcept(is_unsigned_v&lt;S&gt;);</pre>
<div class="desc"><i>Effects:</i> As if an object <code>wi</code> of type <code>wide_integer&lt;Bits, S&gt;</code> was created from input value and the corresponding operator was called for <code>*this</code> and the <code>wi</code>.</div>

<pre>template&lt;typename Integral&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator%=(const Integral&amp;);
template&lt;typename Integral&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator&amp;=(const Integral&amp;) noexcept;
template&lt;typename Integral&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator|=(const Integral&amp;) noexcept;
template&lt;typename Integral&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator^=(const Integral&amp;) noexcept;
template&lt;typename Integral&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator&lt;&lt;=(const Integral&amp;);
template&lt;typename Integral&gt; constexpr wide_integer&lt;Bits, S&gt;&amp; operator&gt;&gt;=(const Integral&amp;) noexcept;</pre>
<div class="desc"><i>Effects:</i> As if an object <code>wi</code> of type <code>wide_integer&lt;Bits, S&gt;</code> was created from input value and the corresponding operator was called for <code>*this</code> and the <code>wi</code>.</div>


<h4>26.??.2.?? wide_integer observers <span class="right">[numeric.wide_integer.observers]</span></h4>
<pre>template &lt;typename Arithmetic&gt; constexpr operator Arithmetic() const noexcept;</pre>
<div class="changed-deleted">
<div class="desc"><i>Returns:</i> If <code>Arithmetic</code> type is an integral type then it is constructed from <code>*this</code> using the integral conversion rules [conv.integral]. Otherwise <code>Arithmetic</code> is constructed from <code>*this</code> using the floating-integral conversion rules [conv.fpint].</div>

<pre>constexpr explicit operator bool() const noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>true</code> if <code>*this</code> is not equal to 0.</div>
</div>


<div class="changed-added">
<div class="desc"><i>Returns:</i> If <code>is_integral_v&lt;Arithmetic&gt;</code> then <code>Arithmetic</code> is constructed from <code>*this</code> using the integral conversion rules [conv.integral]. If <code>is_floating_point_v&lt;Arithmetic&gt;</code>, then <code>Arithmetic</code> is constructed from <code>*this</code> using the floating-integral conversion rules [conv.fpint]. Otherwise the operator shall not participate in overload resolution.</div>
</div>





<h3>26.??.?? Specializations of common_type <span class="right">[numeric.wide_integer.traits.specializations]</span></h3>

<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
struct common_type&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt; {
  using type = wide_integer&lt;max(Bits, Bits2), <i>see below</i>&gt;;
};</pre>

<p>The signed template parameter indicated by this specialization is following:</p>
<ul>
  <li><code>(is_signed_v&lt;S&gt; &amp;&amp; is_signed_v&lt;S2&gt; ? signed : unsigned)</code> if <code>Bits == Bits2</code></li>
  <li><code>S</code> if <code>Bits > Bits2</code></li>
  <li><code>S2</code> otherwise</li>
</ul>
<p><i>[Note: </i> <code>common_type</code> follows the <i>usual arithmetic conversions</i> design. <i>- end note]</i></p>

<p class="notes"><b><i>[Note:</i></b> <code>common_type</code> attempts to follow the <i>usual arithmetic conversions</i> design here for interoperability between different numeric types. Following two specializations must be moved to a more generic place and enriched with usual arithmetic conversion rules for <b>all the other</b> numeric classes that specialize <code>std::numeric_limits</code><i><b>- end note]</b></i></p>
<pre>template&lt;size_t Bits, typename S, typename Arithmetic&gt;
struct common_type&lt;wide_integer&lt;Bits, S&gt;, Arithmetic&gt; {
  using type = <i>see below</i>;
};</pre>

<pre>template&lt;typename Arithmetic, size_t Bits, typename S&gt;
struct common_type&lt;Arithmetic, wide_integer&lt;Bits, S&gt;&gt;
  : common_type&lt;wide_integer&lt;Bits, S&gt;, Arithmetic&gt;;
</pre>

<p>The member typedef <code>type</code> is following:</p>
<ul>
  <li><code>Arithmetic</code> if <code>numeric_limits&lt;Arithmetic&gt;::is_integer</code> is <code>false</code></li>
  <li><code>wide_integer&lt;Bits, S&gt;</code> if <code>sizeof(wide_integer&lt;Bits, S&gt;) &gt; sizeof(Arithmetic)</code></li>
  <li><code>Arithmetic</code> if <code>sizeof(wide_integer&lt;Bits, S&gt;) &lt; sizeof(Arithmetic)</code></li>
  <li><code>Arithmetic</code> if <code>sizeof(wide_integer&lt;Bits, S&gt;) == sizeof(Arithmetic) &amp;&amp; is_signed_v&lt;S&gt;</code></li>
  <li><code>Arithmetic</code> if <code>sizeof(wide_integer&lt;Bits, S&gt;) == sizeof(Arithmetic) &amp;&amp; numeric_limits&lt;wide_integer&lt;Bits, S&gt;&gt;::is_signed == numeric_limits&lt;Arithmetic&gt;::is_signed</code></li>
  <li><code>wide_integer&lt;Bits, S&gt;</code> otherwise</li>
</ul>

<h3>26.??.?? Unary operators <span class="right">[numeric.wide_integer.unary_ops]</span></h3>
<pre>template&lt;size_t Bits, typename S&gt; constexpr wide_integer&lt;Bits, S&gt; operator~(const wide_integer&lt;Bits, S&gt;&amp; val) noexcept;</pre>
<div class="desc"><i>Returns:</i> value with inverted significant bits of <code>val</code>.</div>

<pre>template&lt;size_t Bits, typename S&gt; constexpr wide_integer&lt;Bits, S&gt; operator-(const wide_integer&lt;Bits, S&gt;&amp; val) noexcept(is_unsigned_v&lt;S&gt;);</pre>
<div class="desc"><i>Returns:</i> <code>val *= -1</code> if <code>S</code> is true, otherwise the result is unspecified.</div>

<pre>template&lt;size_t Bits, typename S&gt; constexpr wide_integer&lt;Bits, S&gt; operator+(const wide_integer&lt;Bits, S&gt;&amp; val) noexcept(is_unsigned_v&lt;S&gt;);</pre>
<div class="desc"><i>Returns:</i> <code>val</code>.</div>

<h3>26.??.?? Binary operators <span class="right">[numeric.wide_integer.binary_ops]</span></h3>
<p>In the function descriptions that follow, <code>CT</code> represents <code>common_type_t&lt;A, B&gt;</code>, where <code>A</code> and <code>B</code> are the types of the two arguments to the function.</p>

<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
  constexpr operator*(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) *= rhs</code>.</div>

<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
  constexpr operator/(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) /= rhs</code>.</div>


<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
  constexpr operator+(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept(is_unsigned_v&lt;S&gt;);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) += rhs</code>.</div>


<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
  constexpr operator-(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept(is_unsigned_v&lt;S&gt;);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) -= rhs</code>.</div>


<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
  constexpr operator%(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) %= rhs</code>.</div>


<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
  constexpr operator&amp;(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) &amp;= rhs</code>.</div>

<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
  constexpr operator|(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) |= rhs</code>.</div>

<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, wide_integer&lt;Bits2, S2&gt;&gt;
  constexpr  operator^(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) ^= rhs</code>.</div>

<pre>template&lt;size_t Bits, typename S&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, size_t&gt;
  constexpr operator&lt;&lt;(const wide_integer&lt;Bits, S&gt;&amp; lhs, size_t rhs);</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) &lt;&lt;= rhs</code>.</div>


<pre>template&lt;size_t Bits, typename S&gt;
  common_type_t&lt;wide_integer&lt;Bits, S&gt;, size_t&gt;
  constexpr operator&gt;&gt;(const wide_integer&lt;Bits, S&gt;&amp; lhs, size_t rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>CT(lhs) &gt;&gt;= rhs</code>.</div>




<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  constexpr bool operator&lt;(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>true</code> if value of <code>CT(lhs)</code> is less than the value of <code>CT(rhs)</code>.</div>


<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  constexpr bool operator&gt;(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>true</code> if value of <code>CT(lhs)</code> is greater than the value of <code>CT(rhs)</code>.</div>


<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  constexpr bool operator&lt;=(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>true</code> if value of <code>CT(lhs)</code> is equal or less than the value of <code>CT(rhs)</code>.</div>


<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  constexpr bool operator&gt;=(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>true</code> if value of <code>CT(lhs)</code> is equal or greater than the value of <code>CT(rhs)</code>.</div>


<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  constexpr bool operator==(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>true</code> if significant bits of <code>CT(lhs)</code> and <code>CT(rhs)</code> are the same.</div>

<pre>template&lt;size_t Bits, typename S, size_t Bits2, typename S2&gt;
  constexpr bool operator!=(const wide_integer&lt;Bits, S&gt;&amp; lhs, const wide_integer&lt;Bits2, S2&gt;&amp; rhs) noexcept;</pre>
<div class="desc"><i>Returns:</i> <code>!(CT(lhs) == CT(rhs))</code>.</div>



<h3>26.??.?? Numeric conversions <span class="right">[numeric.wide_integer.conversions]</span></h3>
<pre>template&lt;size_t Bits, typename S&gt; std::string to_string(const wide_integer&lt;Bits, S&gt;&amp; val);
template&lt;size_t Bits, typename S&gt; std::wstring to_wstring(const wide_integer&lt;Bits, S&gt;&amp; val);</pre>
<div class="desc"><i>Returns:</i> Each function returns an object holding the character representation of the value of its argument. All the significant bits of the argument are outputed as a signed decimal in the style <code>[-]dddd</code>.</div>

<div>
<pre>
template &lt;size_t Bits, typename S&gt;
to_chars_result to_chars(char* first,
                       char* last,
                       const wide_integer&lt;Bits, S&gt;&amp; value,
                       int base = 10);
</pre>
<p>Behavior of <code>wide_integer</code> overload is subject to the usual rules of primitive numeric output conversion functions [utility.to.chars].</p>

<pre>template &lt;size_t Bits, typename S&gt;
from_chars_result from_chars(const char* first,
                           const char* last,
                           wide_integer&lt;Bits, S&gt;&amp; value,
                           int base = 10);
</pre>
<p>Behavior of <code>wide_integer</code> overload is subject to the usual rules of primitive numeric input conversion functions [utility.from.chars].</p>
</div>

<h3>26.??.?? iostream specializations <span class="right">[numeric.wide_integer.io]</span></h3>
<pre>template&lt;class Char, class Traits, size_t Bits, typename S&gt;
basic_ostream&lt;Char, Traits&gt;&amp; operator&lt;&lt;(basic_ostream&lt;Char, Traits&gt;&amp; os, const wide_integer&lt;Bits, S&gt;&amp; val);</pre>
<div class="desc"><i>Effects:</i> As if by: <code>os &lt;&lt; to_string(val)</code>.</div>
<div class="desc"><i>Returns:</i> <code>os</code>.</div>


<pre>template&lt;class Char, class Traits, size_t Bits, typename S&gt;
basic_istream&lt;Char, Traits&gt;&amp; operator&gt;&gt;(basic_istream&lt;Char, Traits&gt;&amp; is, wide_integer&lt;Bits, S&gt;&amp; val);</pre>
<div class="desc"><i>Effects:</i> Extracts a <code>wide_integer</code> that is represented as a decimal number in the <code>is</code>. If bad input is encountered, calls <code>is.setstate(ios_base::failbit)</code> (which may throw <code>ios::failure</code> ([iostate.flags])).</div>
<div class="desc"><i>Returns:</i> <code>is</code>.</div>


<h3>26.??.?? Hash support <span class="right">[numeric.wide_integer.hash]</span></h3>
<pre>template&lt;size_t Bits, typename S&gt; struct hash&lt;wide_integer&lt;Bits, S&gt;&gt;;</pre>
<p>The specialization is enabled (20.14.14). If there is a built-in integral type <code>Integral</code> that has the same typename and width as <code>wide_integer&lt;Bits, S&gt;</code>, and <code>wi</code> is an object of type <code>wide_integer&lt;Bits, S&gt;</code>, then <code>hash&lt;wide_integer&lt;MachineWords, S&gt;&gt;()(wi) == hash&lt;Integral&gt;()(Integral(wi))</code>.</p>


        <h2>V. Feature-testing macro</h2>
        <p>For the purposes of SG10 we recommend the feature-testing macro name <code>__cpp_lib_wide_integer</code>.</p>

        <h2 class="changed-added">VI. Acknowledgements</h2>
        <p class="changed-added">Many thanks to Alex Strelnikov	and John McFarlane for sharing useful ideas and thoughts.</p>

        <script type="text/javascript">
            function colorize_texts(texts) {
                for (var i = 0; i < texts.length; ++i) {
                    var text = texts[i].innerHTML;
                    text = text.replace(/namespace|sizeof|long|enum|void|constexpr|extern|noexcept|bool|template|class |struct|auto|const|typename|explicit|public|private|operator|#include|inline| char|typedef|static_assert|static_cast|static/g,"<span class='cppkeyword'>$&<\/span>");
                    text = text.replace(/\/\/[\s\S]+?\n/g,"<span class='cppcomment'>$&<\/span>");
                    //text = text.replace(/\"[\s\S]+?\"/g,"<span class='cpptext'>$&<\/span>");
                    texts[i].innerHTML = text;
                }
            }

            colorize_texts(document.getElementsByTagName("pre"));
            colorize_texts(document.getElementsByTagName("code"));

            function show_hide_deleted() {
                var to_change = document.getElementsByClassName('changed-deleted');
                for (var i = 0; i < to_change.length; ++i) {
                    to_change[i].style.display = (document.getElementById("show_deletions").checked ? 'block' : 'none');
                }
            }
            show_hide_deleted()
        </script>
</body></html>
