<!DOCTYPE html>
<html>
<head>
<meta charset="ASCII">
<style type="text/css">
body { color: #000000; background-color: #FFFFFF; }
del { text-decoration: line-through; color: #8B0040; }
ins { text-decoration: underline; color: #005100; }

p.example { margin-left: 2em; }
pre.example { margin-left: 2em; }
div.example { margin-left: 2em; }

code.extract { background-color: #F5F6A2; }
pre.extract { margin-left: 2em; background-color: #F5F6A2;
  border: 1px solid #E1E28E; }

p.function { }
.attribute { margin-left: 2em; }
.attribute dt { float: left; font-style: italic;
  padding-right: 1ex; }
.attribute dd { margin-left: 0em; }

blockquote.std { color: #000000; background-color: #F1F1F1;
  border: 1px solid #D1D1D1;
  padding-left: 0.5em; padding-right: 0.5em; }
blockquote.stddel { text-decoration: line-through;
  color: #000000; background-color: #FFEBFF;
  border: 1px solid #ECD7EC;
  padding-left: 0.5empadding-right: 0.5em; ; }

blockquote.stdins { text-decoration: underline;
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3; padding: 0.5em; }

table { border: 1px solid black; border-spacing: 0px;
  margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }
td { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }
  
.highlight .hll { background-color: #ffffcc }
.highlight  { background: #ffffff; }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #FF0000; background-color: #FFAAAA } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .o { color: #333333 } /* Operator */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #557799 } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0044DD } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #003388; font-weight: bold } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #333399; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #6600EE; font-weight: bold } /* Literal.Number */
.highlight .s { background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #0000CC } /* Name.Attribute */
.highlight .nb { color: #007020 } /* Name.Builtin */
.highlight .nc { color: #BB0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
.highlight .ni { color: #880000; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #FF0000; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066BB; font-weight: bold } /* Name.Function */
.highlight .nl { color: #997700; font-weight: bold } /* Name.Label */
.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #007700 } /* Name.Tag */
.highlight .nv { color: #996633 } /* Name.Variable */
.highlight .ow { color: #000000; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #6600EE; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #6600EE; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #005588; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #4400EE; font-weight: bold } /* Literal.Number.Oct */
.highlight .sb { background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #0044DD } /* Literal.String.Char */
.highlight .sd { color: #DD4422 } /* Literal.String.Doc */
.highlight .s2 { background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #666666; font-weight: bold; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { background-color: #eeeeee } /* Literal.String.Interpol */
.highlight .sx { color: #DD2200; background-color: #fff0f0 } /* Literal.String.Other */
.highlight .sr { color: #000000; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #AA6600 } /* Literal.String.Symbol */
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700; font-weight: bold } /* Name.Variable.Global */
.highlight .vi { color: #3333BB } /* Name.Variable.Instance */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
</style>
<title>is_contiguous_layout</title>
</head>

<body>

<h1>is_contiguous_layout</h1>
<p>ISO/IEC JTC1 SC22 WG21 P0258R0 - 2016-02-12<br />
Michael Spencer &lt;bigcheesegs@gmail.com&gt;<br />
Audience: EWG, LEWG<br />
</p>

<section>
<h2 id="intro">Introduction</h2>
<p>This paper proposes adding a new compiler-backed type trait to enable
portably hashing an object as a range of bytes.
</p>

<code class="highlight"><span class="k">template</span> &lt;<span class="k">class</span> T&gt; <span class="k">struct</span> is_contiguous_layout;</code>
</section>

<section>
<h2 id="usage">Usage</h2>
<pre><code class="highlight"><span class="k">struct</span> <span class="n">Trivial</span> <span class="p">{</span>
  <span class="kt">char</span> <span class="o">*</span><span class="n">Data</span><span class="p">;</span>
  <span class="kt">unsigned</span> <span class="n">Len</span><span class="p">;</span>
<span class="p">};</span>

<span class="c1">// Assert that Trivial can be hashed as a range of bytes if it is contiguous layout.</span>
<span class="k">namespace</span> <span class="n">std</span> <span class="p">{</span>
  <span class="k">template</span> <span class="o">&lt;&gt;</span>
  <span class="k">struct</span> <span class="n">is_uniquely_represented</span><span class="o">&lt;</span><span class="n">Trivial</span><span class="o">&gt;</span>
    <span class="o">:</span> <span class="n">is_contiguous_layout</span><span class="o">&lt;</span><span class="n">Trivial</span><span class="o">&gt;</span> <span class="p">{};</span>
<span class="p">}</span></code></pre>
</section>

<section>
<h2 id="motive">Motivation</h2>
<p><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0029r0.html">
P0029</a> proposes the user specialized trait
<code>is_uniquely_represented</code> to assert that an object of a given type
can be hashed by hashing its object representation. It states that
<code>is_uniquely_represented</code> can only be true for types which have no
padding bits, but intentionally avoids adding a type trait to check this to keep
the proposal a "pure library" proposal.
</p>

<p>It is not possible for users to portably assert that a type has the
<code>is_uniquely_represented</code> trait without compiler assistance.</p>

<h3 id="motive-trivial">Trivial Example</h3>
<pre><code class="highlight"><span class="k">struct</span> <span class="n">Trivial</span> <span class="p">{</span>
  <span class="kt">char</span> <span class="o">*</span><span class="n">Data</span><span class="p">;</span>
  <span class="kt">unsigned</span> <span class="n">Len</span><span class="p">;</span>
<span class="p">};</span>
</code></pre>

<p>The contiguous hashibility of this type depends on:

<ol>
<li>The <code>sizeof</code> <code>Data</code>, <code>Len</code> and
<code>Trivial</code>. <code>sizeof(Data) + sizeof(Len)</code> must equal
<code>sizeof(Trivial)</code>.</li>
<li>The implementation defined mapping between pointer values and their object
representation.</li>
<li>The implementation defined mapping between unsigned values and their object
representation.</li>
</ol></p>

<p>1 can be checked via a static assert, however this is verbose.</p>

<p>2 and 3 can only be checked by reading the documentation for your
implementation for every platform you intend to target, thus limiting
portability.</p>

<h3 id="motive-bitfields">Bitfields</h3>
<pre><code class="highlight"><span class="k">struct</span> <span class="n">Bitfields</span> <span class="p">{</span>
  <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">A</span> <span class="p">:</span> <span class="mi">4</span><span class="p">;</span>
  <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">B</span> <span class="p">:</span> <span class="mi">4</span><span class="p">;</span>
  <span class="kt">unsigned</span> <span class="kt">short</span> <span class="n">C</span> <span class="p">:</span> <span class="mi">8</span><span class="p">;</span>
<span class="p">};</span>
</code></pre>

<p>The contiguous hashibility of this type depends on how bitfields are
implemented. In practice this is different between the Itanium ABI and Visual
C++. This can also only be checked by taking a look at the docs.</p>
</section>

<section>
<h2 id="design">Design Implications</h2>
<p>The proposed wording for this trait is: </p>
<blockquote>
<p>A <var>contiguous-layout</var> type is a <var>standard-layout</var> type for
which all bits in the object representation participate in the value
representation (3.9).
</p>
</blockquote>
<p>This means that a standard-layout type is a contiguous-layout type unless
there exist two object representation bit patterns of the type for which there
exists no well defined program operating only on value representations to
observe the difference.</p>

<h3 id="design-floats">Floats</h3>
<p>Floating point values may compare equal even when they have different object
representations. However this does not preclude them from having
contiguous-layout types, as equality is not the only way to observe the
difference between floating point values. The implementation may provide enough
tools to observe the full state of the value.</p>

<p>It is implementation defined if floating point types are contiguous-layout.
</p>

<h3 id="design-unions">Unions</h3>
<p>Unions with members which are all the same size and are all contiguous-layout
types are also obvious candidates for contiguous-layout types. However, unions
with members of different sizes present a problem, as the existence of padding
bits depends on the active member.</p>

<p>For union members which do not share a common initial sequence,
implementations are allowed to omit copying the entire object representation of
a union if it knows the active member. It is completely reasonable for an
implementation to do this if a member was just assigned.</p>

<p>It is implementation defined if union types are contiguous-layout.</p>
</section>

<section>
<h2 id="std">Proposed Wording</h2>
<p>Proposed wording changes to the standard.
</p>

<h3>3.9 Types [basic.types]</h3>
<p>Add a new paragraph.
</p>
<blockquote class="stdins">
<p>A <var>contiguous-layout</var> type is a <var>standard-layout</var> type for
which all bits in the object representation participate in the value
representation (3.9).
</p>
</blockquote>

<h3>20.10.2 Header <code>&lt;type_traits&gt;</code> synopsis [meta.type.synop]</h3>
<p>Add to synopsis.
</p>
<blockquote class="stdins">
<code>template &lt;class T&gt; struct is_contiguous_layout;</code>
</blockquote>

<h3>20.10.4.3 Type properties [meta.unary.prop]</h3>
<p>Add to table 49 - Type property predicates.
</p>
<blockquote class="stdins">
<table is="cxx-table">
  <thead>
    <tr>
      <th>Template</th>
      <th>Condition</th>
      <th>Preconditions</th>
    </tr>
  </thead>
  <tr>
    <td><code>template &lt;class T&gt; struct is_contiguous_layout;</code></td>
    <td>T is a contiguous-layout type (3.9)</td>
    <td>T shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.</td>
  </tr>
</table>
</blockquote>
</section>

<section>
<h2 id="ref">References</h2>
<ul>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0029r0.html">
P0029</a> - A Unified Proposal for Composable Hashing, Geoff Romer, Chandler Carruth</li>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3333.html">
N3333</a> - Hashing User-Defined Types in C++1y, Jeffrey Yasskin, Chandler Carruth</li>
</ul>
</section>

</body>
</html>
