<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <meta name="generator" content="pandoc" />
  <title></title>
  <style type="text/css">code{white-space: pre;}</style>
  <style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
  margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
  </style>
</head>
<body>
<h1 id="simply-a-strong-variant">Simply a Strong Variant</h1>
<ul>
<li>Document number: P0093R0</li>
<li>Date: 2015-09-24</li>
<li>Project: ISO/IEC JTC1 SC22 WG21</li>
<li>Reply-to: David Sankel <script type="text/javascript">
<!--
h='&#x73;&#116;&#x65;&#108;&#108;&#x61;&#114;&#x73;&#x63;&#x69;&#x65;&#110;&#x63;&#x65;&#46;&#x63;&#x6f;&#x6d;';a='&#64;';n='&#100;&#x61;&#118;&#x69;&#100;';e=n+a+h;
document.write('<a h'+'ref'+'="ma'+'ilto'+':'+e+'" clas'+'s="em' + 'ail">'+e+'<\/'+'a'+'>');
// -->
</script><noscript>&#100;&#x61;&#118;&#x69;&#100;&#32;&#x61;&#116;&#32;&#x73;&#116;&#x65;&#108;&#108;&#x61;&#114;&#x73;&#x63;&#x69;&#x65;&#110;&#x63;&#x65;&#32;&#100;&#x6f;&#116;&#32;&#x63;&#x6f;&#x6d;</noscript></li>
</ul>
<h2 id="introduction">Introduction</h2>
<p>There is wide agreement that C++ needs a type-safe union type and the significant number of &quot;variant&quot; implementations in the wild confirms that it fills a practical need for many developers.<a href="#fn1" class="footnoteRef" id="fnref1"><sup>1</sup></a> On the other hand, how exactly to implement a variant has been an item of much controversy of late. This is witnessed by many hundreds of variant emails on the standard library mailing list and the heated discussions invoked by related blog posts.<a href="#fn2" class="footnoteRef" id="fnref2"><sup>2</sup></a><a href="#fn3" class="footnoteRef" id="fnref3"><sup>3</sup></a> The danger, of course, with all the controversy is that consensus will not be achieved and that software developers will suffer the effects of widespread divergent implementations of a library considered to be an essential &quot;vocabulary&quot; type.</p>
<p>This paper is an attempt to bridge the divide by proposing a hitherto undiscussed option. To the author's surprise, this attempt at a compromise has the unusual properties of being both more flexible and more simple (in both specification and usage) than the competing alternatives.</p>
<p>In a nutshell, we are proposing a variant implementation that has the never-empty guarantee, preserves <strong>strong</strong> type safety, and gives implementers the flexibility to optimize their implementations based on the alternative types. As it turns out, this simple specification meets the needs of opposing camps and provides an interface that will allow more optimizations as language improvements come about in the future.</p>
<h2 id="design-considerations">Design Considerations</h2>
<h3 id="never-empty">Never empty</h3>
<p>At the May 2015 meeting at Lenexa there was consensus that the variant type should model the mathematical concept of the discriminated union. This decision led to more consistency and provided guidance as to what the interface should look like. This is particularly true with regard to whether or not to allow repeated alternative types and how to handle conversions.</p>
<p>Although this consensus was achieved at Lenexa, there was a lingering contradiction between the attempt to model a discriminated union and the proposed implementation; namely, there is no mathematical equivalent of an &quot;invalid&quot; state. Although the committee took pains to limit the conditions required to get into the invalid sate, it nonetheless complicated the semantics of variant. Consider the following function declaration:</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="dt">void</span> f( std::variant&lt;A,B,C&gt; &amp; );</code></pre></div>
<p><code>f</code> may or may not be able to properly handle an &quot;invalid&quot; variant. Although most functions with variant parameters do not <em>need</em> to handle an &quot;invalid&quot; variant, there are some that do and we need to distinguish between them. This can be somewhat obviated by having a coding standard that states &quot;unless otherwise specified, variant parameters have a validity precondition&quot;, but the extra complication of the semantics still remains.</p>
<p>The variant of this proposal completely removes the &quot;invalid&quot; state and, thus, has no difficulties modeling a discriminated union.</p>
<h3 id="why-strong">Why Strong?</h3>
<p>Peter Dimov pointed out that a variant with only basic exception safety is exceedingly difficult to use as a member variable of a class that requires strong exception guarantees. This fact is easy to see when comparing the requisite hurdles to those needed for other standard structures. The main difficulty is that a variant type is not guaranteed have a non-throwing move assignment operator and, thus, <code>swap</code> operation.</p>
<p>In effect, a class with strong exception guarantees with an arbitrary variant member will need to manually double buffer the variant. In the following example we have a class <code>C</code> that has strong exception safety guarantees and a <code>std::variant</code> member variable.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">class</span> C {
<span class="kw">public</span>:
  <span class="co">//...</span>
  std::variant&lt;A,B,C&gt; getVariant() <span class="dt">const</span>;
  <span class="dt">void</span> modifyVariant();
<span class="kw">private</span>:
  <span class="dt">bool</span> m_firstVariantIsTheActiveOne = <span class="kw">true</span>;
  std::pair&lt; std::variant&lt;A,B,C&gt;, std::variant&lt;A,B,C&gt; &gt; m_variant;
};</code></pre></div>
<p>The first thing to note is that the <code>getVariant()</code> function cannot return a <code>const &amp;</code> since the &quot;active&quot; variant can change over time. The second thing to note is that we need a discriminator to maintain which of the two variants is active at any time. The implementations of the member functions follow:</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp">std::variant&lt;A,B,C&gt; C::getVariant() <span class="dt">const</span> {
  <span class="kw">return</span> m_firstVariantIsTheActiveOne ? m_variant.first : m_variant.second;
}

<span class="dt">void</span> C::modifyVariant() {
  <span class="co">// make both variants the same</span>
  <span class="kw">if</span>(m_firstVariantIsTheActiveOne)
    m_variant.second = m_variant.first;
  <span class="kw">else</span>
    m_variant.first = m_variant.second;
  m_firstVariantIsTheActiveOne = <span class="kw">true</span>;

  <span class="co">// Modify &#39;m_variant.second&#39; in a way that could possibly throw an</span>
  <span class="co">// exception.</span>
  <span class="co">// ...</span>
  
  m_firstVariantIsTheActiveOne = <span class="kw">false</span>;
}</code></pre></div>
<p>This methodology differs from how we would implement a class with strong guarantees with any other standard type in the following ways:</p>
<ul>
<li>(basic guarantee styled) variant members restrict what the interface of the class's getters can look like.</li>
<li>(basic guarantee styled) variant members require the class to have additional member variables.</li>
</ul>
<p>Compare this to how modifications to a <code>std::vector</code> in a member function of a class with strong guarantees would be implemented. Special consideration only occurs in the member function itself.</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="dt">void</span> C::modifyVector() {
  std::vector&lt;A&gt; copy = m_vector;

  <span class="co">// Modify &#39;copy&#39; in a way that could possibly throw an exception.</span>
  <span class="co">// ...</span>

  std::swap( copy, m_vector );
}</code></pre></div>
<p>A variant with a strong exception safety guarantee (or more specifically a strong exception safety preserving guarantee) would not require any special considerations for this use case and that is what is being proposed in this paper.</p>
<h3 id="performance-implications">Performance implications</h3>
<p>A naive implementation of the proposed library would use double buffering as a means to provide strong exception safety guarantees. This implementation path has an important drawback: every variant instance would have a size that is twice that of the largest alternative type. None of the other variants proposed thus far have this drawback.</p>
<p>On closer inspection, however, one can see that not all variants would require double buffering. For example, if every alternative of a variant type has a non-throwing move constructor there is no need for double buffering. This is notably true for all built-in types. A non-double buffered variant could also be created if alternatives only supported non-throwing move assignment operations by using the stack for temporary values. This applies, or could apply, to most standard types.</p>
<p>While this proposal does not require implementations to take advantage of these optimizations, a quality implementation would make use of these strategies when possible, relieving the developer from these concerns.</p>
<p>One oft-cited concern is developers who are writing high-performance code. The underlying assumption is that they would not find double-buffering acceptable under any circumstances. The author speculates that these same developers are happy to trade program correctness for speed by avoiding exception safety issues by either disabling them or making use of <code>union</code>s in non-robust ways.</p>
<p>Even those developers, however, are supported by this proposal. They can make use of the <code>noexcept</code> keyword on the possibly exception-throwing move-constructors of the alternatives they use in the variant to ensure double-buffering is disabled on quality implementations. One may claim that these extra steps would be tedious, but the author of this paper argues that this is a feature; writing non-robust code should be made tedious by design.</p>
<h3 id="surprise-a-future-proof-interface">Surprise: a future proof interface</h3>
<p>Another, perhaps surprising, benefit of this proposal is that <code>variant</code> implementations can improve in performance as C++ gains more relevant features without resorting to changing the interface in possibly breaking ways. Transactional memory, for example, may one day allow all variants to avoid double buffering while always maintaining the strong exception safety guarantee. Other variant proposals that have either an explicit or implicit empty state are, in essence, pessimizing the public interface with regard to future improvements in the language.</p>
<h2 id="conclusion">Conclusion</h2>
<p>The need for a standard variant type is clear. This paper proposes a variant that is simply defined, is easy to use, and meets a wide variety of needs.</p>
<div class="footnotes">
<hr />
<ol>
<li id="fn1"><p>Variant: a type-safe union (v4). N4542<a href="#fnref1">↩</a></p></li>
<li id="fn2"><p><a href="https://www.justsoftwaresolutions.co.uk/cplusplus/standardizing-variant.html">Standardizing Variant: Difficult Decisions</a><a href="#fnref2">↩</a></p></li>
<li id="fn3"><p><a href="http://davidsankel.com/c/a-variant-for-the-everyday-joe/">A variant for the everyday Joe</a><a href="#fnref3">↩</a></p></li>
</ol>
</div>
</body>
</html>
