<?xml version='1.0' encoding='UTF-8'?>

<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.1//EN' 'http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd'>

<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en'>
	<head>
		<title>Checked-dereference conditions</title>
	</head>
	<body>
<h1>Checked-dereference conditions</h1>

<ul>
<li>Document Number: N4127</li>
<li>Date: 2014-07-20</li>
<li>Project: Programming Language C++, Evolution Working Group</li>
<li>Reply-to: Eelis van der Weegen (<a href="mailto:wg21@contacts.eelis.net">wg21@contacts.eelis.net</a>)</li>
</ul>

<h2>I. &nbsp; Introduction</h2>

<p>This is a proposal to add a new form of condition:</p>

<p>
<small>
&emsp;<i>condition:<br/>
&emsp;&emsp;&emsp;expression<sub> </sub><br/>
&emsp;&emsp;&emsp;attribute-specifier-seq<sub>opt</sub> decl-specifier-seq declarator = initializer-clause<br/>
&emsp;&emsp;&emsp;attribute-specifier-seq<sub>opt</sub> decl-specifier-seq declarator braced-init-list<br/>
<span style='color:#00cc00'>
&emsp;&emsp;&emsp;attribute-specifier-seq<sub>opt</sub> decl-specifier-seq declarator : expression<br/>
</span>
</i>
</small>
</p>

<p>
	For example,
	&emsp;<tt>if (T x : e) s</tt>&emsp;
	translates to
	&emsp;<tt>if (auto &amp;&amp; __p = e) { T x = *__p; s }</tt>&emsp;
	for some invisible name <tt>__p</tt>.
</p>

<p>Translation for the new form of condition in a while or for loop is analogous.</p>

<p>The "<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3994.htm">next generation</a>" version where the type defaults to <tt>auto &amp;&amp;</tt> is also proposed.</p>

<h2>II. &nbsp; Motivation</h2>

<p>Range-based for-loops provide syntax that expands into the necessary bookkeeping and dereferencing needed to access the elements of a conventional begin()/end() traversable range.</p>
<p>There is a similar convention for checked access to pointees&mdash;the underlying objects of (smart) pointers and things like <tt>std::optional&lt;&gt;</tt>:</p>
<pre>
	if (std::shared_ptr&lt;T&gt; sp = wp.lock())
	{
		f(*sp);
	}
</pre>
<p>Using the new form of condition, this can be written:</p>
<pre>
	if (T &amp; x : wp.lock())
	{
		f(x);
	}
</pre>
<p>Or, in next-gen form (where the type defaults to <tt>auto &amp;&amp;</tt>):</p>
<pre>
	if (x : wp.lock())
	{
		f(x);
	}
</pre>
<p>Similar to how range-based for hides the iterators and just lets you name the underlying object, a checked-dereference condition hides the pointer-like thing and just lets you name the underlying object.</p>

<h2>III. &nbsp; Use with <code>while()</code></h2>

<p>The new form of condition may also appear in a while loop:</p>
<pre>	while (T x : e) s</pre>
<p>This translates to:</p>
<pre>	while (auto &amp;&amp; __p = e) { T x = *__p; s }</pre>
<p>This can be useful. For example, suppose we have:</p>
<pre>
	std::optional&lt;message&gt; try_read(input &amp;);

	void process(message);
</pre>
<p>then instead of:</p>
<pre>
	while (std::optional&lt;message&gt; m = try_read(i))
	{
		process(*m);
	}
</pre>
<p>we may write:</p>
<pre>
	while (message m : try_read(i))
	{
		process(m);
	}
</pre>
<p>Or, in next-gen form:</p>
<pre>
	while (m : try_read(i))
	{
		process(m);
	}
</pre>

<h2>IV. &nbsp; Use with <code>for()</code></h2>

<p>Since a <i>condition</i> may also appear in a (traditional) for loop, a checked-dereference condition may be used there, too:</p>
<pre>
	for (s1; T x : e1; e2) s2
</pre>
<p>translates to:</p>
<pre>
	for (s1; auto &amp;&amp; __p = e1; e2) { T x = *__p; s2 }
</pre>
<p>This form is not expected to be commonly used, but is easy to support consistently.</p>

<h2>V. &nbsp; Use with <code>switch()</code></h2>

<p>Since a checked-dereference condition would not make much sense for a switch statement's condition,
allowing this use is not proposed (so there would have to be a separate condition grammar production).</p>


<h2>VI. &nbsp; Relation to monadic bind / pattern matching</h2>

<p>The form &emsp;<code>if (T x : e) { ... }</code>&emsp; may remind one of something like</p>
<pre>
	monad_bind(e, [](T x){ ... })
</pre><p>or even</p><pre>
	functor_map(e, [](T x){ ... })
</pre><p>However, these are ways to make additional values "in the monad/functor".</p>
<p>By contrast, the checked-dereference condition is for getting underlying values "out" of the indirection,
and so is more akin to pattern matching. That is,</p><pre>
	if (x : e) s1; else s2;
</pre><p>is comparable to a pattern match like (here shown in Haskell):</p><pre>
	case e of
	    Just x -&gt; s1
	    Nothing -&gt; s2
</pre>

<h2>VII. &nbsp; Implementation</h2>

<p>The author is planning a proof-of-concept implementation in Clang. Implementation experience for range-based and next-generation for suggests that the effort should be minimal.</p>

<h2>VIII. &nbsp; Proposed Wording</h2>

<p>None yet, but can be provided if there is interest.</p>

	</body>
</html>
