<html>
<head>
<title>P0846R0: ADL and Function Templates that are not Visible</title>

<style type="text/css">
  ins { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
  .new { text-decoration:none; font-weight:bold; background-color:#D0FFD0 }
  del { text-decoration:line-through; background-color:#FFA0A0 }  
  strong { font-weight: inherit; color: #2020ff }
  table, td, th { border: 1px solid black; border-collapse:collapse; padding: 5px }
</style>
</head>

<body>
P0846R0<br/>
John Spicer &lt;jhs@edg.com><br/>
Audience: CWG<br/>
2017-11-08<br/>

<h1>P0846R0: ADL and Function Templates that are not Visible<h1>

<h2>Introduction</h2>

<p>
In Toronto (7/2017) core reviewed Robert Haberlach's D0389R1
"template keyword in unqualified-ids".  Core agreed with that the problem
presented but disagreed with the intended solution.
<p>
Instead of requiring the user to use the <code>template</code> keyword,
a revision to the lookup rules was proposed so that a name for which a normal
lookup produces either no result or finds one or more functions
and that is followed by a
a "&lt;" would treated as if
a function template name had been found and would cause ADL to be performed.
<p>
This proposal was brought to the Evolution group in Toronto and it received
strong support (12 | 14 | 0 | 0 | 0).
<p>
It was observed that this change could change code where you have an
overloaded &lt; operator that accepts a function as the left-hand
operand.  This case was considered as pathological case not likely enough
to be of concern.



<h2>Wording changes</h2>

Change 6.4.1 [basic.lookup.unquql] paragraph 3:

<blockquote>

The lookup for an unqualified name used as the <em>postfix-expression</em> of a
function call is described in 6.4.2.
[ Note: For purposes of determining (during parsing) whether an expression is a
<em>postfix-expression</em> for a function call, the usual name lookup rules
apply.
<ins>
In some cases a name followed by &lt; is treated as a <em>template-name</em>
even though name lookup did not find a template-name (see 17.2).  For example,
</ins>


<pre>
<ins>
int h;
void g();
namespace N {
	struct A {};
	template &lt;class T> int f(T);
	template &lt;class T> int g(T);
	template &lt;class T> int h(T);
}

int x = f&lt;N::A>(N::A());  // OK: lookup of f finds nothing,
                          // f treated as template name
int y = g&lt;N::A>(N::A());  // OK: lookup of g finds a function,
                          // g treated as template name
int z = h&lt;N::A>(N::A());  // error: "h&lt;" does not begin a template-id
</ins>
</pre>
The rules in 6.4.2 have no effect on the syntactic interpretation of an
expression. For example,

</blockquote>

Change 17.2 [temp.names] paragraph 2 and 3:

<blockquote>
For a <em>template-name</em> to be explicitly qualified by the template

arguments, the name must be <del>known</del> <ins>considered</ins> to
refer to a template.
<ins>
[Note: Whether a name actually refers to a template cannot be known in some
cases until after argument dependent lookup is done [6.4.2]. -- end note]
A name is considered to refer to a template if name lookup finds a
<em>template-name</em> or a overload set that contains a function template.
A name is also considered to refer to a template if it is an
<em>unqualified-id</em> followed by a &lt; and name lookup finds either one
or more functions or finds nothing.
</ins>

<p>
<del>After name lookup (6.4) finds that a name is</del>
<ins>When a name is considered to be</ins>
a <em>template-name</em>
<del>
or that an operator-function-id or a literal- operator-id refers to a set of
overloaded functions any member of which is a function template</del>,
<del>if this</del> <ins>and it</ins> is followed by a &lt;, the &lt; is always
taken as the delimiter of a
template-argument-list and never as the less-than operator.
</blockquote>

Change 17.3 [temp.arg] paragraph 7:

<blockquote>
When
<del>the template</del>
<ins>
name lookup for the name
</ins>
in a template-id
<del>is an overloaded function template</del>
<ins>finds an overload set</ins>,
both non-template functions in the overload set and function templates
in the overload set ...
</blockquote>



Add a new section to Annex C.6:

<blockquote>
<h3>
<ins>
C.6.X [temp.name]
</ins>
</h3>

<ins>

<b>Change: </b>A <em>unqualified-id</em> that is followed by a &lt;
and for which name lookup finds nothing or finds a function will be treated
as a <em>template-name</em> in order to potentially cause argument dependent
lookup to be performed.
</ins>

<p>
<ins>
<b>Rationale: </b>It was problematic to call a function template with
an explicit template argument list via argument dependent lookup
because of the need to have a template with the same name visible via
normal lookup.
</ins>

<p>
<ins>
<b>Effect on original feature: </b>Previously valid code that uses a function
name as the left operand of a &lt; operator would become ill-formed.
</ins>

<pre>
<ins>
struct A {};
bool operator &lt;(void (*fp)(), A);
void f(){}
int main() {
  A a;
  f &lt; a;  // ill-formed; previously well-formed
  (f) &lt; a;  // still well formed
}
</ins>
</pre>

</blockquote>

</body>
</html>

