<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

<style type="text/css">
pre {margin-left:20pt; }
pre > i {
  font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
code > i {
  font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
pre > em {
  font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
code > em {
  font-family: "OCR A Extended", "Consolas", "Lucida Console", monospace;
  font-style:italic;
}
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.header { border: 0px; border-spacing: 0;
  margin-left: 0px; font-style: normal; }

table { border: 1px solid black; border-spacing: 0px;
  margin-left: auto; margin-right: auto; }
th { text-align: left; vertical-align: top;
  padding-left: 0.4em; border: none; 
  padding-right: 0.4em; border: none; }
td { text-align: left; vertical-align: top;
  padding-left: 0.4em; border: none;
  padding-right: 0.4em; border: none; }
</style>

<title>Keep alias syntax extendable</title>
</head>

<body>

<table class="header"><tbody>
  <tr>
    <th>Document number:&nbsp;&nbsp;</th><th> </th><td>P0831R0</td>
  </tr>
  <tr>
    <th>Date:&nbsp;&nbsp;</th><th> </th><td>2017-10-14</td>
  </tr>
  <tr>
    <th>Project:&nbsp;&nbsp;</th><th> </th><td>Programming Language C++, Library Evolution Working Group</td>
  </tr>
  <tr>
    <th>Reply-to:&nbsp;&nbsp;</th><th> </th><td><address>Tomasz Kamiński &lt;tomaszkam at gmail dot com&gt;</address></td>
  </tr>
</tbody></table>

<h1><a name="title">Keep alias syntax extendable</a></h1>

<h2><a name="intro">1. Introduction</a></h2>

<p>This document proposes to reduce the scope of the <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0634r0.pdf">P0634: Down with <code>typename</code>!</a> paper,
   to exclude alias declaration.</p>

<p>Following the current direction of the above paper, the following syntax:</p>
<pre>using <em>id</em> = <em>some-other-id</em>;</pre>
<p>will be restricted to type alias declarations, and by doing so, it will prevent its possible further extension: to alias other kind of entities (functions, variables).</p>

<!--h2><a name="toc">Table of contents</a></h2-->

<!--h2><a name="history">2. Revision history</a></h2-->


<h2><a name="motivation">2. Motivation and Scope</a></h2>

<p>Features presented in this paper, are used to illustrate the possible extension of the <code>alias declaration</code> syntax, that would
   be blocked by acceptance of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0634r0.pdf">P0634R0</a> paper in its current form.
   They are <b>not proposed</b> as part of this paper.</p>

<h3><a name="motivation.function-aliasing">2.1. Importing function from other namespace</a></h3>

<p>Currently if we want to import an (set of) function <code>foo</code> defined in namespace <code>X</code> into
   namespace <code>Y</code>, we can use using-declaration syntax:</p>
<pre>using Y::foo;</pre>

<p>However, there is no corresponding syntax that would allow to import a function under a different name.
   As an alternative, we may define a new function <code>bar</code> in namespace <code>X</code> that would perfect-forward
   to our target function.</p>

<p>Let our start will the following definition:</p>
<pre>namespace X {
  template&lt;typename... Args&gt;
  decltype(auto) bar(Args&amp;&amp;... args)
  { return Y::foo(std::forward&lt;Args&gt;(args)...); }
}</pre>

<p>For above declaration, there are two major differences between the behaviour of the <code>X::bar</code> and <code>Y::foo</code> invocations:</p>
<ul>
  <li><code>X::bar</code> is never <code>noexcept</code>, even if corresponding invocation of <code>Y::foo</code> would be,</li>
  <li><code>X::bar</code> will lead to hard error, in situation when the invocation of <code>Y:foo</code> would lead only to a SFINAE'able error.</li>
</ul>

<p>To fix both above problem we need to introduce conditional <code>noexcept</code> specification and change the return type specification:</p>
<pre>namespace X {
  template&lt;typename... Args&gt;
  auto bar(Args&amp;&amp;... args)
    noexcept(noexcept(Y::foo(std::forward&lt;Args&gt;(args)...)))
    -&gt; decltype(Y::foo(std::forward&lt;Args&gt;(args)...))
  { return Y::foo(std::forward&lt;Args&gt;(args)...); }
}</pre>

<p>Still, with the introduction of Concepts Lite, the above declaration may not be equivalent, as function <code>X::bar</code> 
   is unconstrained, while the corresponding <code>Y::foo</code> function may be, which would lead to selecting a different overload
   during overload resolution. As consequence, to preserve such behaviour, the user is required to repeat signatures of all of the <code>Y::foo</code> overloads.</p>

<p>Finally, even if the user will carefully repeat the signature of the original function, invocation may still may not be equivalent due use of forwarding,
   that may lead to materialization of temporary and invocation of move constructor. To illustrate, if we have a non-moveable type <code>NonMovable</code>  and the following declarations:</p>
<pre>namespace Y {
  void foo(NonMovable);
}

namespace X {
  void bar(NonMovable&amp;&amp; nm) { return Y::foo(std::move(nm)); }
}</pre>

<p>the invocation <code>X::bar(NonMovable{})</code> will be ill-formed, while <code>Y::foo(NonMovable[})</code> is fine. This scenario may be considered
   an edge case, but additional move-construction (that may degenerate to copy) may have a measurable impact on performance.</p>

<p>The author believes that above problems with achieving the simple goal of importing function with different name, shows that the function
   aliasing feature would be compelling and needed addition to the language &mdash; it is worth to remind at this point that none of above issues
   would occur if we decide to reuse same name and use <code>using Y::foo;</code> instead.</p> 

<h3><a name="motivation.syntax">2.2. Reusing type alias syntax</a></h3>

<p>As the using-declaration can be used to import any kind of entity from the other namespace, we may expect that the similar
   type alias syntax could be extended to allow function aliases, leading to the following solution to the problem described in 2.1:</p>
<pre>namespace X {
  using bar = Y::foo;
}</pre> 

<p>The major concern with this solution, is that its introduces more ambiguity to the language - it is not clear from the
   syntax what kind of entity is being imported (function, type, template, variable?). To address this, we may follow the namespace
   alias design, and provide separate syntax for each kind of entity.</p>

<p>On the other hand, if the intent of the user is to make call to <code>X::bar</code> equivalent to the <code>Y::foo</code>,
   we may argue, that the syntax should not differ and depend on the fact if the <code>Y::foo</code> is implemented as:<p>
<ul>
  <li>function,</li>
  <li>set of overloaded functions,</li>
  <li>function template,</li>
  <li>set of overloaded function templates,</li>
  <li>set of overloaded functions and function templates,</li>
  <li>global functor variable, mimicking <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html">STL2 customization points design</a>.</li>
</ul>
  
<p>Otherwise, the selection of appropriate alias syntax and updating it accordingly puts a lot of burden on the user.</p>

<p>The author believes that both above approaches have their own drawbacks and benefits, and blocking one of the solutions at this point
    would be an mistake, and might impede the future evolution of the language.</p>

<h2><a name="acknowledgements">3. Acknowledgements</a></h2>

<p>Andrzej Krzemieński offered many useful suggestions and corrections to the proposal.</p>

<p>Special thanks and recognition goes to Sabre (<a href="http://www.sabre.com/">http://www.sabre.com</a>) for supporting the production of this proposal.</p>

<h2><a name="literature">4. References</a></h2>

<ol>
  <li>Daveed Vandevoorde, 
      "Down with <code>typename</code>!" 
      (P0634R0, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0634r0.pdf">
                         http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0634r0.pdf</a>)</li>

  <li>Eric Niebler, 
      "Suggested Design for Customization Points" 
      (N4381, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html">
                       http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html</a>)</li>

</ol>

</body></html>
