<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC
    "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN"
    "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">
<html xml:lang='en' xmlns:svg='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/1999/xhtml'>
<head><meta content='application/xhtml+xml;charset=utf-8' http-equiv='Content-type' /><title>ContainerIncomplete Type</title></head>
<body><!-- maruku -o incomplete.html incomplete.md --><style type='text/css'>
pre>code { display: block; margin-left: 2em; }
code { white-space: pre-wrap; }
ins { text-decoration: none; font-weight: bold; background-color: #A0FFA0 }
del { text-decoration: line-through; background-color: #FFA0A0 }
</style><table><tbody>
<tr><th>Doc. no.:</th>	<td>N3890</td></tr>
<tr><th>Date:</th>	<td>2014-01-19</td></tr>
<tr><th>Project:</th>	<td>Programming Language C++, Library Evolution Working Group</td></tr>
<tr><th>Reply-to:</th>	<td>Zhihao Yuan &lt;zy at miator dot net&gt;</td></tr>
</tbody></table>
<h1 id='containerincomplete_type'>Container&#60;Incomplete Type&#62;</h1>

<h2 id='overview'>Overview</h2>

<pre><code>struct Entry
{
    std::deque&lt;Entry&gt; messages;
    // ...
};</code></pre>

<p>The goal of this paper is to allow recursive data structure definitions with STL containers, while to make the STL container instantiations well-formed even when some of the template arguments are incomplete types (in contrast to 17.6.4.8/2) is an approach to achieve the goal without breaking any language restrictions or existing practices.</p>

<p>The approach, namely &#8220;Containers of Incomplete Types&#8221;, was well-known shortly after the C++98 standard being shipped<code>[1]</code>, is one of the main features provided by Boost.Container<code>[2]</code> and libstdc++, and is receiving increasing interest in libc++.</p>

<p>Some workarounds have been discussed, including using a container of smart pointers. However, the proposed solution has the following significant advantages:</p>

<ol>
<li>The value semantics of <code>value_type</code> is well-preserved;</li>

<li>scoped allocators work out-of-box;</li>

<li>such a container can be used in type erasure.</li>
</ol>

<h2 id='impact_on_the_standard'>Impact on the Standard</h2>

<ol>
<li>
<p>An additional &#8220;Completeness&#8221; requirement for each category of the containers &#8211; Sequence, Associative, Unordered associative, and Container adaptors, plus the Hash requirements and Allocator requirements.</p>
</li>

<li>
<p>Require the unspecialized and transparent function objects (<code>std::less&lt;T&gt;</code> and <code>std::less&lt;&gt;</code>, for example, respectively) to be complete types unconditionally.</p>
</li>

<li>
<p>Require <code>std::allocator&lt;T&gt;</code> to unconditionally satisfy the &#8220;Allocator completeness requirements&#8221; in 1).</p>
</li>
</ol>

<p>2) and 3) are trivial to the existing implementations, but not 1). Some changes involve ABI breakages, and some changes result in less compile-time checking; but run-time performance will not be affected (interestingly, the situation is similar to that of the SCARY iterators, as well as some techniques we are using, plus some goals we want to achieve from a type system&#8217;s point of view).</p>

<p>Currently,</p>

<ul>
<li>
<p>libc++ can fully satisfy the proposed solution after being patched (see <a href='#sample_implementation'>Sample Implementation</a>, but with an ABI breakage on <code>std::deque</code>;</p>
</li>

<li>
<p>libstdc++ can satisfy the proposed solution with some untested changes made to the unordered associative containers;</p>
</li>

<li>
<p>MSVC STL perfers to perserve some compile-time constants for debugger visualization on <code>std::deque</code> (read as &#8220;the solution remains unknown&#8221;), and is interested in patching <code>std::list</code> and <code>std::forward_list</code>.</p>
</li>
</ul>

<h2 id='design_decisions'>Design Decisions</h2>

<p>The proposed feature set is chosen in a &#8220;least common multiple&#8221; (of the existing implementations) manner. All the possible (no <code>std::array</code>) and useful cases are conditionally covered, so that only the standard library implementations may be affected, but not existing user code. For example, if a customized <code>MyLess</code> is not a complete type, the whole <code>std::set&lt;T, MyLess&gt;</code> specialization is not well-formed.</p>

<h2 id='technical_specifications'>Technical Specifications</h2>

<p>This specification only covers 1) in <a href='#impact_on_the_standard'>Impact on the Standard</a>; 2) and 3) are merely wording details.</p>

<h4 id='hash_completeness_requirements'>Hash completeness requirements</h4>

<p>A type <code>H</code> satisfies the Hash completeness requirements if:</p>

<ul>
<li>it is a function object type,</li>

<li>it is a complete type, and</li>

<li><code>h(k)</code> is well formed when treated as an unevaluated operand.</li>
</ul>

<p><em>[Just a note:</em> <code>h</code> and <code>k</code> are defined in 17.6.3.4 <em>&#8211;end note]</em></p>

<h4 id='allocator_completeness_requirements'>Allocator completeness requirements</h4>

<p>A type <code>X</code> satisfies the Allocator completeness requirements if:</p>

<ul>
<li>it is a complete type, and</li>

<li><code>X::value_type</code> is defined and identical to <code>T</code>.</li>
</ul>

<p><em>[Just a note:</em> If <a href='http://cplusplus.github.io/LWG/lwg-active.html#2311'>LWG 2311</a> is applied, this section may no longer be needed. <em>&#8211;end note]</em></p>

<h4 id='sequence_containers'>Sequence containers</h4>

<p>A sequence container with an <code>Allocator</code> template parameter is a complete type if:</p>

<ul>
<li>the argument of <code>Allocator</code> satisfies the Allocator completeness requirements.</li>
</ul>

<h4 id='associative_containers'>Associative containers</h4>

<p>An associative container is a complete type if:</p>

<ul>
<li>the argument of <code>Compare</code> is a complete type, and</li>

<li>the argument of <code>Allocator</code> satisfies the Allocator completeness requirements.</li>
</ul>

<h4 id='unordered_associative_containers'>Unordered associative containers</h4>

<p>An unordered associative container is a complete type if:</p>

<ul>
<li>the argument of <code>Hash</code> satisfies the Hash completeness requirements,</li>

<li>the argument of <code>Pred</code> is a complete type, and</li>

<li>the argument of <code>Alloc</code> satisfies the Allocator completeness requirements.</li>
</ul>

<h4 id='container_adaptors'>Container adaptors</h4>

<ul>
<li>the argument of <code>Compare</code>, if any, is a complete type, and</li>

<li>the argument of <code>Container</code> is a complete type, and <code>Container::size_type</code> is a complete type.</li>
</ul>

<h2 id='sample_implementation'>Sample Implementation</h2>

<p>The proposed solution has been implemented (as an llvm/libc++ fork) and well- tested: <a href='https://github.com/lichray/libcxx/tree/container_incomplete'>https://github.com/lichray/libcxx/tree/container_incomplete</a></p>

<h2 id='references'>References</h2>

<p><code>[1]</code> Austern, Matthew H. <em>The Standard Librarian: Containers of Incomplete Types</em>. <a href='http://www.drdobbs.com/the-standard-librarian-containers-of-inc/184403814'>http://www.drdobbs.com/the-standard-librarian-containers-of-inc/184403814</a></p>

<p><code>[2]</code> <em>Main features: Containers of Incomplete Types</em>. &#8220;Boost.Container&#8221; <a href='http://www.boost.org/doc/libs/1_55_0/doc/html/container/main_features.html#container.main_features.containers_of_incomplete_types'>http://www.boost.org/doc/libs/1_55_0/doc/html/container/main_features.html#container.main_features.containers_of_incomplete_types</a></p>

<h2 id='acknowledgments'>Acknowledgments</h2>

<p>Thanks to the library implementers who helped refine the idea, run my crappy test code, and review the patches publicly and/or privately.</p>
</body></html>
