<html>
<head>
<title>P0301R1: Wording for Unified Call Syntax (revision 1)</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 }
  .rule { background-color:#FFFF40 }
  .ex { background-color: #D0FFF0 }
  del { text-decoration:line-through; background-color:#FFA0A0 }  
  strong { font-weight: inherit; color: #2020ff }
</style>
</head>

<body>
P0301R1<br/>
Jens Maurer &lt;Jens.Maurer@gmx.net><br/>
Audience: Evolution Working Group<br/>
2016-03-21<br/>

<h1>P0301R1: Wording for Unified Call Syntax (revision 1)</h1>

<h2>Introduction</h2>

The previous revision of this paper, P0301R0, attempted to faithfully
provide a suggestion for alternative wording to implement the
semantics outlined in P0251R0 Unified Call Syntax Wording by Bjarne
Stroustrup and Herb Sutter, based on the EWG consensus from Kona:

<ul>
<li>For <code>f(x,y)</code>, see if <code>f(x,y)</code> is valid and
if so do that call; otherwise try <code>x.f(y)</code>.</li>
</ul>

The phrase "is valid" was clarified to mean "at least one viable
function was found".  This approach failed to achieve consensus in the
WG21 plenary in Jacksonville.

<p>

Deviating from P0251R0 and its companion and predecessor papers, I now
propose a separate syntax for achieving unified call semantics, also
allowing chaining:

<ul>

<li> <code>.f(x,y)</code> produces a merged overload set of
<code>f(x,y)</code> and <code>x.f(y)</code> and invokes the best
viable function, preferring the member function in case of a tie.</li>

<li> <code>.x.f(y)</code> is equivalent to <code>.f(x,y)</code></li>

<li>chaining is supported: <code>.x.f(y).g(z)</code> is equivalent to
<code>.g(.f(x,y), z)</code></li>

</ul>


<h2>Design</h2>

See

<ul>
<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4474.pdf">N4474</a> Unified Call Syntax: x.f(y) and f(x,y) (Bjarne Stroupstrup and Herb Sutter)</li>

<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0131r0.pdf">P0131R0</a> Unified call syntax concerns (Bjarne Stroustrup)</li>

<li><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0079r0.pdf">P0079R0</a> Extension methods for C++ (Jonathan Coe, Roger Orr)</li>

</ul>

As far as I understand, the main motivation for a unified call
approach was to have a single call syntax addressing both member and
non-member functions in the context of a template.  This becomes more
important as concepts allow to easily probe for a certain function
call to be valid, but users are presumed not to care whether the
functionality is provided by a member function or a non-member
function.

<p>
The use-case to adapt classes to requirements expected by third-party
templates is not supported, unless the new syntax is used:

<pre>
// library 1
template&lt;class T>
int f(const T& x) {
  return x.weight();       // cannot call non-member weight(S)
  // return .x.weight();   // would call non-member weight(S)
}

// library 2
struct S {
  int get_weight() const;
};

// adapter
int weight(const S& s) {
  return s.get_weight();
}

// application
S s;
int value = f(s);  // x.weight() ought to invoke weight(S), but is ill-formed
</pre>


<h2>Examples</h2>

<blockquote>
<pre>
struct S {
  int f();
  static bool g();
  int h(int);
  int (*fp)();
};
int f(int);
int h(S, char *);
int h(S, int *);
int (*fp)(S);

S s;
int x1 = .f(1);    // ok, calls ::f(int)
int x2 = .f(s);    // ok, equivalent to s.f()
bool x4 = .g(s);   // ok, equivalent to s.g()
int x5 = .h(s, 0); // ok, equivalent to s.h(0) (better match)
int x6 = .s.h(0);  // ok, equivalent to s.h(0) (better match)
int x7 = .h(s, nullptr);  // error: ambiguous
int x8 = .fp(s);   // ok, prefer s.fp() (member over non-member)
</pre>
</blockquote>


<h2>Open Issues</h2>

The wording proposal below still has defects in at least the following
areas:

<ul>

<li>in a postfix-expression linked to a unified call introducer, a
class member access (5.2.5) is allowed to be applied to a non-class
(but requires a function call, then)</li>

<li>the function call section 5.2.2 needs to be checked again for the
conditions when overload resolution applies, and when the given
function is invoked directly.  For example, does .x.f(y) invoke
.f(x,y) (with full overload resolution) if "f" is a function pointer?
[Suggested answer: Yes.]</li>

<li>14.2p4 might need an update so that the <code>template</code>
keyword is not required for unified calls</li>

<li>5.2.2p4 needs to specify the argument list for a unified function
call (which might not be the argument list given by the syntax)</li>

</ul>


<h2>Wording</h2>

Change 3.4.5 [basic.lookup.classref] paragraph 1:

<blockquote>
In a class member access expression (5.2.5 [expr.mem]) <ins>that is
not linked to a unified call introducer (5.2 [expr.post])</ins>, if
the . or -> token is immediately followed by an identifier followed by
a &lt;, the identifier must be looked up to determine whether the &lt;
is the beginning of a template argument list (14.2) or a less-than
operator. The identifier is first looked up in the class of the object
expression. If the identifier is not found, it is then looked up in
the context of the entire postfix-expression and shall name a class
template. <ins>In a class member access linked to a unified call
introducer where the . or -> token is immediately followed by an
<em>identifier</em> followed by a &lt;, the <em>identifier</em> shall
name a template. [ Note: When a class member access is linked to a
unified call introducer and appears as the <em>postfix-expression</em>
of a function call, both member and non-member lookup is performed; see
13.3.1.1 [over.match.call]. -- end note ]</ins>

</blockquote>

Change the grammar for <em>postfix-expression</em> in 5.2 [expr.post]:

<blockquote>
<pre>
<em>postfix-expression:
       <ins>.<sub>opt</sub></ins> primary-expression
       postfix-expression [ expr-or-braced-init-list ]
       postfix-expression ( expression-list<sub>opt</sub> )
       ...</em>
</pre>
</blockquote>

Add a new paragraph after 5.2 [expr.post] paragraph 2:

<blockquote class="new">
A <em>postfix-expression</em> that is a <em>primary-expression</em>
prefixed by . (dot) is called a <em>unified call introducer</em>.  Its
type, value category, and value are the same as those of the
<em>primary-expression</em>. [ Note: A unified call introducer
modifies the semantics of member and non-member function calls (5.2.2
[expr.call], 13.3.1.1 [over.match.call]). -- end note ]  A
<em>postfix-expression</em> E1 is <em>linked</em> to a
<em>postfix-expression</em> E2 if

<ul>
<li>E2 is the initial part of E1 or</li>
<li>E1 is linked to a <em>postfix-expression</em> E and E is linked to E2.</li>
</ul>

A <em>full postfix-expression</em> is a <em>postfix-expression</em>
such that no other <em>postfix-expression</em> is linked to it.  A
full <em>postfix-expression</em> that is linked to a unified call
introducer shall either be a function call (5.2.2 [expr.call]) or be
linked to one.  [ Example:

<pre>
struct S {
  struct M { int i; } m;
  M f();
} s;
int x1 = s.m.i;       // ok
int x2 = .s.m.i;      // error: no function call
int x3 = .s.f().m.i;  // ok
</pre>
-- end example ]

</blockquote>

Split and change 5.2.2 [expr.call] paragraph 1 - 3:

<blockquote>
A function call is a <del>postfix expression</del>
<ins><em>postfix-expression</em></ins> followed by parentheses
containing a possibly empty, comma-separated list of
<em>initializer-clause</em>s which constitute the arguments to the
function.

<p>

<ins>If the <em>postfix-expression</em> is a pointer-to-member
expression (5.5 [expr.mptr.oper]) of function type, that member
function is selected. Otherwise, if the <em>postfix-expression</em>
has class type, is an <em>id-expression</em>, optionally prefixed by
. (dot), or is a class member access (5.2.5 [expr.mem] linked to a
unified call introducer (5.2 [expr.post]), overload resolution is
applied to select the best viable function (13.3.1.1
[over.match.call], 13.3 [over.match]).  Otherwise, the
<em>postfix-expression</em> shall be a prvalue of function pointer
type or an lvalue of function type and the function pointed to or
referred to is selected. [ Note: The function-to-pointer standard
conversion (4.3) is not applied. -- end note ]</ins>


<del>The postfix expression shall have function type or function pointer
type. For a call to a non-member function or to a static member
function, the postfix expression shall be either an lvalue that refers
to a function (in which case the function-to-pointer standard
conversion (4.3) is suppressed on the postfix expression), or it shall
have function pointer type.</del>  <del>Calling a function through an
expression whose function type has a language linkage that is
different from the language linkage of the function type of the called
function's definition is undefined (7.5).</del> <del>For a call to a
non-static member function, the postfix expression shall be an
implicit (9.3.1, 9.4) or explicit class member access (5.2.5) whose
id-expression is a function member name, or a pointer-to-member
expression (5.5) selecting a function member; the call is as a member
of the class object referred to by the object expression.  In the case
of an implicit class member access, the implied object is the one
pointed to by this. [ Note: a member function call of the form f() is
interpreted as (*this).f() (see 9.3.1). -- end note ]</del>

<del>If a function or member function name is used, the name can be
overloaded (Clause 13), in which case the appropriate function shall
be selected according to the rules in 13.3 [over.match].</del>

<p>
If the selected function is non-virtual, or if the
<em>id-expression</em> in the class member access expression is a
<em>qualified-id</em>, that function is called. Otherwise, its final
overrider (10.3) in the dynamic type of the object expression is
called; such a call is referred to as a virtual function call. [ Note:
the dynamic type is the type of the object referred to by the current
value of the object expression. 12.7 describes the behavior of virtual
function calls when the object expression refers to an object under
construction or destruction. -- end note ]

<p>
[ Note: If a function or member function name is used, and name lookup
(3.4) does not find a declaration of that name, the program is
ill-formed. No function is implicitly declared by such a call. -- end
note ]

<p>
If the <em>postfix-expression</em> designates a destructor (12.4), the type of
the function call expression is void; otherwise, the type of the
function call expression is the return type of the statically chosen
function (i.e., ignoring the virtual keyword), even if the type of the
function actually called is different. This return type shall be an
object type, a reference type or cv void.

<p>
<ins>Calling a function through an expression whose function type has
a language linkage that is different from the language linkage of the
function type of the called function's definition is undefined
(7.5).</ins>

</blockquote>


Change in 5.2.5 [expr.ref] paragraph 2:

<blockquote>
For the first option (dot) the first expression shall have complete
class type. For the second option (arrow) the first expression shall
have pointer to complete class type. The expression E1->E2 is
converted to the equivalent form (*(E1)).E2; the remainder of 5.2.5
will address only the first option (dot). [ Footnote: ... ] <del>In
either case,</del> <ins>Unless the class member access is linked to a
unified call introducer (5.2 [expr.post]),</ins> the
<em>id-expression</em> shall name a member of the class or of one of
its base classes. [ Note: because the name of a class is inserted in
its class scope (Clause 9), the name of a class is also considered a
nested member of that class. -- end note ] [ Note: 3.4.5 describes how
names are looked up after the . and -> operators.  -- end note ]

</blockquote>

Add a new bullet in 13.3.3 [over.match.best] paragraph 1 after bullet 7:

<blockquote>
<ul>

<li>F1 and F2 are function template specializations, and the function
template for F1 is more specialized than the template for F2 according
to the partial ordering rules described in 14.5.6.2<ins>, or, if not
that,</ins></li>

<li><ins>the context is a function call (13.3.1.1 [over.match.call])
linked to a unified call introducer and F1 is a member function and F2
is a non-member function</ins>.</li>

</ul>

</blockquote>


Change in 13.3.1.1 [over.match.call] :

<blockquote>
In a function call (5.2.2 [expr.call])
<pre>
       <em>postfix-expression ( expression-list<sub>opt</sub> )</em>
</pre>

<del>if the <em>postfix-expression</em> denotes a set of overloaded
functions and/or function templates, overload resolution is applied as
specified in 13.3.1.1.1 [over.call.func]. If the
<em>postfix-expression</em> denotes an object of class type, overload
resolution is applied as specified in 13.3.1.1.2
[over.call.object].</del>

<ins>the set of candidate functions is determined from the
<em>postfix-expression</em> and the argument types in the
<em>expression-list</em>.</ins>

</blockquote>

<blockquote class="new">

<ul>

<li>If the <em>postfix-expression</em> is a unified call introducer
(5.2 [expr.post]) or is linked to one, the set of candidate functions
is determined as specified in 13.3.1.1.3 [over.call.unified].</li>

<li>Otherwise, if the <em>postfix-expression</em> has class type, the
set of candidate functions is determined as specified in 13.3.1.1.2
[over.call.object].</li>

<li>Otherwise, the set of candidate functions is determined as specified in 13.3.1.1.1 [over.call.func].</li>

</ul>

</blockquote>

Change in section 13.3.1.1.2 [over.call.object] paragraph 1:

<blockquote>
If the <del><em>primary-expression</em></del>
<ins><em>postfix-expression</em></ins> E in the function call syntax
evaluates to a class object of type "cv T", then the set of candidate
functions includes at least the function call operators of T. The
function call operators of T are obtained by ordinary lookup of the
name operator() in the context of (E).operator().

</blockquote>

Add a new section 13.3.1.1.3 [over.call.unified]:

<blockquote class="new">

<h3>13.3.1.1.3 Unified function call [over.call.unified]</h3>

A partial candidate set is determined from a result of name lookup as
follows:

<ul>

<li>For a variable of type pointer to function (or
reference thereto), the set consisting of a surrogate call function
constructed from its function type;</li>

<li>otherwise, for an object of class type, the candidate set
determined for a call to an object of class type (13.3.1.1.2
[over.call.object]);</li>

<li>otherwise, the candidate set determined for a call to a named
function (13.3.1.1.1 [over.call.func]).</li>

</ul>


If the <em>postfix-expression</em> in the function call syntax is a
unified call introducer (5.2 [expr.post]), the set of candidate
functions is the union of the following sets:

<ul>

<li>If name lookup (3.4 [basic.lookup]) for the
<em>primary-expression</em> finds one or more class members, the set
of functions found by argument-dependent lookup (3.4.2
[basic.lookup.argdep]),</li>

<li>the partial candidate set from the result of name lookup, and</li>

<li>if the first element of the <em>expression-list</em> (if any) has
class type, the partial candidate set from a class member access
lookup (3.4.5 [basic.lookup.classref]) where the first element of the
<em>expression-list</em> is the object expression and the
<em>id-expression</em> is the <em>primary-expression</em> of the
function call, in which case the argument list consists of the
remainder of the <em>expression-list</em>.</li>

</ul>

[ Example:
<pre>
  namespace N {
    struct A { };
    void f();
  }
  int (*f)();
  struct S {
    int f(N::A);
    int x = .f(S(), N::A());  // all functions and function pointers named "f" are candidates
                              // only S::f(N::A) is viable
  };
</pre>
-- end example ]

<p>

If the <em>postfix-expression</em> is a class member access linked to
a unified call introducer, the set of candidate functions is the union
of the following sets:

<ul>

<li>The partial candidate set from the result of class member access
lookup (3.4.5 [basic.lookup.classref]) and</li>

<li>the partial candidate set from a lookup of the
<em>primary-expression</em> and the set of functions found by
argument-dependent lookup; in both cases the object expression is
prepended to the <em>expression-list</em>.</li>

</ul>

[ Example:
<pre>
  namespace N {
    struct A { };
    void f();
  }
  int (*f)();
  struct S {
    int f(N::A);
    int x = .S().f(N::A());  // all functions and function pointers named "f" are candidates;
                             // only S::f(N::A) is viable
  };
</pre>
-- end example ]
<p>

[ Example:
<pre>
  struct S {
    int f();
    static bool g();
    int h(int);
    int (*fp)();
  };
  int f(int);
  int h(S, char *);
  int h(S, int *);
  int (*fp)(S);

  S s;
  int x1 = .f(1);    // ok, calls ::f(int)
  int x2 = .f(s);    // ok, equivalent to s.f()
  bool x4 = .g(s);   // ok, equivalent to s.g()
  int x5 = .h(s, 0); // ok, equivalent to s.h(0) (better match)
  int x6 = .s.h(0);  // ok, equivalent to s.h(0) (better match)
  int x7 = .h(s, nullptr);  // error: ambiguous
  int x8 = .fp(s);   // ok, prefer s.fp() (member over non-member)

  struct X {
    S m;
  } x;
  int x9 = .f(g(s));           // error; S::g is not a candidate
  int x9b = .f(.g(s));         // ok; equivalent to ::f(s.g())
  int q(int, int);
  int x10 = .x.m.f().q(5);     // ok; equivalent to .q(.f(x.m), 5)
  int x11 = .(x.m.f()).q(7);   // ok; equivalent to .q(x.m.f(), 7)
  int x12 = (.x.m.f()).q(8);   // error: no member "q" in non-class type "int"
</pre>
-- end example ]


</blockquote>

Change in 14.6.2 [temp.dep] paragraph 1:

<blockquote>
... In an expression of the form:
<pre>
      <em>postfix-expression ( expression-list<sub>opt</sub> )</em>
</pre>

where the <em>postfix-expression</em> is an <em>unqualified-id</em>
<ins>optionally prefixed by . (dot) or a class member access (5.2.5
[class.mem]) linked to a unified call introducer (5.2 [expr.post])
with the <em>id-expression</em> of the class member access an
<em>unqualified-id</em></ins>, the <em>unqualified-id</em> denotes a
dependent name if

<ul>

<li>any of the expressions in the expression-list is a pack expansion
(14.5.3)</li>

<li>any of the expressions or <em>braced-init-list</em>s in the
<em>expression-list</em> is type-dependent (14.6.2.2),
<del>or</del></li>

<li><ins>in the case of a class member access, the object expression
is type-dependent, or</ins></li>

<li>the <em>unqualified-id</em> is a <em>template-id</em> in which any
of the template arguments depends on a template parameter.</li>

</ul>

</blockquote>


<h2>Acknowledgements</h2>

The <code>.f(x)</code> syntax or slight variations thereof were
proposed by several parties informally, including Mikhail Semenov in
c++std-ext-16355, Dawn Perchik, and Daveed Vandevoorde.  Thanks to
Dawn Perchik for suggestions on the wording.

</body>
</html>
