<html> 
  <style type="text/css">
body { color: #000000; background-color: #FFFFFF; }
ins, ins * { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
del, del * { text-decoration:line-through; background-color:#FFA0A0 }
#hidedel:checked ~ * del, #hidedel:checked ~ * del * { display:none; visibility:hidden }

p, li, blockquote {
    font-family: "sans", Times, serif;
    font-size: 11pt
}
h1, h2, h3 {font-family: "sans", Times, serif;}
h4 {font-family: "sans", Times, serif; margin-top:0.25em;}

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: #FFFFFF;
  border: 1px solid #E1E28E; font-family: "monospace"; }

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 { 
  color: #000000; background-color: #C8FFC8;
  border: 1px solid #B3EBB3; padding: 0.5em; padding-top:0; }

blockquote pre em { font-family: 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.8em; border: none; }
td { text-align: left; vertical-align: top;
  padding-left: 0.8em; border: none; }
  

ul { list-style-type: none; }
a { text-decoration: none; }

ul > li:before {
	content: "\2014";
	position: absolute;
	margin-left: -1.5em; 
}


p.grammarlhs { font-style:italic; margin-bottom: 0; margin-top: 0em }
p.grammarrhs { font-style:italic; margin-left:8em; margin-top:0; margin-bottom: 0; text-indent:-4em }
p.grammarrrhs { font-style:italic; margin-left:12em; margin-top:0; margin-bottom: 0; text-indent:-4em }
p.grammarlhs tt { font-style:normal }
p.grammarrhs tt { font-style:normal }
p.grammarrrhs tt { font-style:normal }

  </style>
  <title>Proposal: template keyword in unqualified-ids</title>
</head><body>

<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.4.0/styles/idea.min.css">
<script src="http://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.4.0/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>

<div style="text-align: right; float: right;">
<p>ISO/IEC JTC1 SC22 WG21, Evolution Working Group<br>
P0389R0<br>
Robert Haberlach (rh633{at}cam{dot}ac.uk)<br>
2016-06-28</p>
</div>
	
	<h2><tt>template</tt> keyword in <em>unqualified-id</em>s</h2>
	<p>This is analogous to evolution issue 92<sup><a href="#EWG92">[EWG92]</a></sup>.</p>
	<br>
	<h3>Motivation</h3>
	<p>Calls to function templates are occasionally unable to exploit ADL, because when specifying a <em>template-id</em> in such cases without any suitably declared template in reach,
	the <tt>&lt;</tt> token is treated as the less-than operator. Consider the example in core issue 687<sup><a href="#CWG687">[CWG687]</a></sup>:</p>
<pre class="extract"><code>namespace N {
	struct A { };
	template &lt;typename T>
	T func(const A&) { return T(); }
}

void f() {
	N::A a;
	func&lt;int>(a);    // error
}</code></pre><p>Qualifying <tt>func</tt> is possible but has different semantics. Instead, it would be optimal to apply the <tt>template</tt> keyword in order to disambiguate.
	This paper proposes to permit the <tt>template</tt> keyword in function calls by augmenting the definition of <em>postfix-expression</em>s accordingly.</p>
	
	<p>Note that the <em>literal-operator-id</em> case is included purely for consistency, as all involved types are fundamental (cf. [over.literal] &para;5) (i.e. ADL is inapplicable).</p>

	<h3>Wording</h3>
	
	<p>Augment 5.2 [expr.post] &para;1 as indicated:</p>
	
	<blockquote class="std">
		<p class="grammarlhs">postfix-expression:</p>
		<p class="grammarrhs"><ins><tt>template</tt> template-id <tt>(</tt> expression-list<sub>opt</sub> <tt>)</tt></ins></p>
	</blockquote>
		
	<p>Modify 14.2 [temp.names] &para;2 as indicated:</p>
	
	<blockquote class="std">For a <em>template-name</em> to be explicitly qualified by the template arguments, the name must be known to refer
to a template <ins>or be prefixed by the <tt>template</tt> keyword</ins>.</blockquote>

	<p>Modify 14.2 [temp.names] &para;3 as indicated:</p>
	<blockquote class="std">
		After name lookup (3.4) finds that a name is a <em>template-name</em> or that an <em>operator-function-id</em> or a <em>literal-operator-id</em>
		refers to a set of overloaded functions any member of which is a function template,
		 <ins>or the name is prefixed by the keyword <tt>template</tt>,</ins> if <del>this</del><ins>the name</ins> is
		followed by a <tt>&lt;</tt>, the <tt>&lt;</tt> is always taken as the delimiter of a <em>template-argument-list</em> and never as the less-than
		operator.
	</blockquote>
	
	<p>Augment 14.2 [temp.names] &para;4 as indicated:</p>
	<blockquote class="std"> [&hellip;]	
	[ <em>Example</em>:<pre class="example"><code>struct X {
  template &lt;std::size_t> X* alloc();
  template &lt;std::size_t> static X* adjust();
};
template &lt;class T> void f(T* p) {
  T* p1 = p->alloc&lt;200>();          // ill-formed: &lt; means less than
  T* p2 = p->template alloc&lt;200>(); // OK: &lt; starts template argument list
  T::adjust&lt;100>();                 // ill-formed: &lt; means less than
  T::template adjust&lt;100>();        // OK: &lt; starts template argument list
}

<ins>template &lt;typename T>
struct B {
  template &lt;typename U>
  void f();
};
template &lt;typename T>
struct D : B&lt;T> {
  void g() {
    f&lt;T>();                // ill-formed: &lt; means less than
    template f&lt;T>();       // OK: &lt; starts template argument list
  }
};

template &lt;typename T>
struct E {
  void bar() {
    h&lt;int>(T{});           // ill-formed: &lt; means less than
    template h&lt;int>(T{});  // OK: &lt; starts template argument list. 
                           // h can be found by argument-dependent name lookup
                           // in the template instantiation context.
  }
};
</ins></code></pre>&mdash; <em>end example</em> ]

	</blockquote>
	

	<p>Modify 14.2 [temp.names] &para;5 as indicated (this simultaneously resolves core issue 1794<sup><a href="#CWG1794">[CWG1794]</a></sup>):</p>
	<blockquote class="std">A name prefixed by the keyword <tt>template</tt> shall be a <em>template-id</em> or the name shall refer to a class template <ins>or alias template</ins>.
	[ <em>Note</em>: The keyword <tt>template</tt> may not be applied to non-template members of class templates. &mdash; <em>end note</em>]
	[ <em>Note</em>: As is the case with the <tt>typename</tt> prefix, the <tt>template</tt> prefix is allowed in cases where it is
	not strictly necessary; i.e., when the <em>nested-name-specifier</em> or the expression on the left of the <tt>-></tt> or <tt>.</tt> is not
	dependent on a <em>template-parameter</em>, or <del>the use does not appear in the scope of a template</del> <ins>the subsequent name would be found to refer to  a template via 
	unqualified name lookup (3.4.1)</ins>. &mdash;<em>end note</em> ]</blockquote>
	<p>NB: The first note refers to temploids and should stay as is.</p>

<h3>Acknowledgments</h3>
<p>The author would like to thank Daveed Vandevoorde for assistance in preparing the wording.</p>

<h3><a id="References">References</a></h3>
<p>[<a id="CWG1794">CWG1794</a>] &ldquo;<tt>template</tt> keyword and alias templates&ldquo;: <a href="http://wg21.link/cwg1794">wg21.link/cwg1794</a></p>
<p>[<a id="CWG687">CWG687</a>] &ldquo;<tt>template</tt> keyword and alias templates&ldquo;: <a href="http://wg21.link/cwg687">wg21.link/cwg687</a></p>
<p>[<a id="EWG92">EWG92</a>] &ldquo;[tiny] Core issue 687, <tt>template</tt> keyword with <em>unqualified-id</em>s&ldquo;: <a href="http://wg21.link/ewg92">wg21.link/ewg92</a></p>
	</body>
</html>
